@walrosproject/ui 0.4.6 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -73,6 +73,30 @@ const theme = useWalrosTheme({
73
73
  <DirectionalCursor />
74
74
  ```
75
75
 
76
+ ## Decoración estacional
77
+
78
+ `WalrosSeasonalBackground` envuelve la interfaz y coloca sus decoraciones SVG en una capa de fondo: nunca se superponen al contenido, no ocupan espacio, no capturan interacción y respetan `prefers-reduced-motion`. El calendario automático se resuelve en `Europe/Madrid` y se actualiza al siguiente cambio de día.
79
+
80
+ - Halloween: desde el 30 de septiembre a las 00:00 hasta el 1 de noviembre a las 00:00.
81
+ - Navidad: desde el 30 de noviembre a las 00:00 hasta el 11 de enero a las 00:00.
82
+ - San Valentín: desde el 14 de febrero a las 00:00 hasta el 15 de febrero a las 00:00.
83
+
84
+ ```tsx
85
+ import { WalrosSeasonalBackground } from "@walrosproject/ui";
86
+
87
+ export function App() {
88
+ return (
89
+ <WalrosSeasonalBackground density={20} style={{ background: "var(--page-background)" }}>
90
+ <YourApp />
91
+ </WalrosSeasonalBackground>
92
+ );
93
+ }
94
+ ```
95
+
96
+ Para que todos los SVG conserven exactamente la misma presencia, aplica el fondo general de la página al wrapper (mediante `style` o su clase) y deja transparente el contenedor principal. Los fondos opacos de tarjetas y secciones seguirán ocultando correctamente las decoraciones que pasen por detrás.
97
+
98
+ Para previsualizar una temporada sin esperar a la fecha, utiliza `season="halloween"`, `season="winter"` o `season="valentine"`. `season="none"` desactiva la capa. Una vez integrado y desplegado, las campañas se activan cada año sin actualizar los repositorios.
99
+
76
100
  ## Otros recursos
77
101
 
78
102
  El paquete conserva `WalrosLogo`, `WalrosWordmark` y sus URLs de imagen. Todos los componentes funcionan con React 18 y 19. El portal y el glitch respetan `prefers-reduced-motion`.
@@ -0,0 +1,17 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 160" fill="none">
2
+ <defs>
3
+ <linearGradient id="heart" x1="40" y1="51" x2="123" y2="129" gradientUnits="userSpaceOnUse">
4
+ <stop stop-color="#FF5457"/>
5
+ <stop offset="1" stop-color="#D41E32"/>
6
+ </linearGradient>
7
+ <linearGradient id="gold" x1="24" y1="24" x2="135" y2="133" gradientUnits="userSpaceOnUse">
8
+ <stop stop-color="#FFE958"/>
9
+ <stop offset="1" stop-color="#F3AE19"/>
10
+ </linearGradient>
11
+ </defs>
12
+ <path d="M80 137S28 107 28 64c0-20 14-34 33-34 10 0 16 5 19 12 3-7 9-12 19-12 19 0 33 14 33 34 0 43-52 73-52 73Z" fill="url(#heart)" stroke="#C92735" stroke-width="7" stroke-linejoin="round"/>
13
+ <path d="M76 44c-13-9-28-2-33 12" stroke="#FF9A90" stroke-width="6" stroke-linecap="round" opacity=".45"/>
14
+ <path d="m18 43 37-16-16 37-21-21ZM142 117l-37 16 16-37 21 21Z" fill="url(#gold)" stroke="#D8A91C" stroke-width="5" stroke-linejoin="round"/>
15
+ <path d="m31 53 96 72" stroke="#F5B415" stroke-width="13" stroke-linecap="round"/>
16
+ <path d="M72 89c0-16 11-24 24-22" stroke="#AE1830" stroke-width="9" stroke-linecap="round"/>
17
+ </svg>
@@ -0,0 +1,17 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 160" fill="none">
2
+ <defs>
3
+ <linearGradient id="pumpkin" x1="28" y1="44" x2="133" y2="132" gradientUnits="userSpaceOnUse">
4
+ <stop stop-color="#FF9F17"/>
5
+ <stop offset="1" stop-color="#F06408"/>
6
+ </linearGradient>
7
+ <linearGradient id="stem" x1="83" y1="15" x2="105" y2="55" gradientUnits="userSpaceOnUse">
8
+ <stop stop-color="#45933D"/>
9
+ <stop offset="1" stop-color="#1D642C"/>
10
+ </linearGradient>
11
+ </defs>
12
+ <path d="M88 45c-2-14 3-26 14-34 11 7 17 17 16 31-1 8-5 13-12 15-8 3-15-2-18-12Z" fill="url(#stem)"/>
13
+ <path d="M80 36c-36 0-61 22-61 57 0 34 24 53 61 53s61-19 61-53c0-35-25-57-61-57Z" fill="url(#pumpkin)"/>
14
+ <path d="M80 38c-18 14-23 75 0 106M51 44c-17 22-17 64 0 94M109 44c17 22 17 64 0 94" stroke="#FFBE3C" stroke-width="5" stroke-linecap="round" opacity=".6"/>
15
+ <path d="m47 82 16-20c2-3 6-3 8 1l8 24c1 4-3 7-7 6l-22-4c-4-1-5-4-3-7ZM113 82 97 62c-2-3-6-3-8 1l-8 24c-1 4 3 7 7 6l22-4c4-1 5-4 3-7ZM78 91l-10 12c-3 3-1 8 4 8h17c5 0 7-5 4-8L83 91c-1-2-4-2-5 0Z" fill="#3A260F"/>
16
+ <path d="M45 112c-2-5 4-8 8-5l10 7 10-7c2-2 5-2 7 0l10 7 10-7c4-3 10 0 8 5l-9 28c-1 4-5 5-8 3l-11-8-11 8c-3 2-7 1-8-3l-16-28Z" fill="#3A260F"/>
17
+ </svg>
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as react from 'react';
2
- import { ImgHTMLAttributes, CSSProperties, RefObject } from 'react';
2
+ import { ImgHTMLAttributes, CSSProperties, ReactNode, RefObject } from 'react';
3
3
 
4
4
  type PortalOrigin = {
5
5
  centerX: number;
@@ -62,6 +62,28 @@ type WalrosThemeGlitchProps = {
62
62
  };
63
63
  declare function WalrosThemeGlitch({ active, zIndex, className, style, }: WalrosThemeGlitchProps): react.JSX.Element;
64
64
 
65
+ type WalrosSeason = "auto" | "none" | "halloween" | "winter" | "valentine";
66
+ type WalrosSeasonalBackgroundProps = {
67
+ children: ReactNode;
68
+ /** Uses the seasonal calendar when set to auto. */
69
+ season?: WalrosSeason;
70
+ /** Time zone used by automatic mode. Defaults to Europe/Madrid. */
71
+ timeZone?: string;
72
+ /** Number of decorations distributed throughout the page. Defaults to 20. */
73
+ density?: number;
74
+ enabled?: boolean;
75
+ className?: string;
76
+ contentClassName?: string;
77
+ style?: CSSProperties;
78
+ };
79
+ type ActiveSeason = Exclude<WalrosSeason, "auto" | "none">;
80
+ /**
81
+ * Returns the campaign active on a date in the selected time zone.
82
+ * Each interval includes its start at 00:00 and excludes its stated end at 00:00.
83
+ */
84
+ declare function getWalrosSeason(date?: Date, timeZone?: string): ActiveSeason | null;
85
+ declare function WalrosSeasonalBackground({ children, season, timeZone, density, enabled, className, contentClassName, style, }: WalrosSeasonalBackgroundProps): react.JSX.Element;
86
+
65
87
  type WalrosTheme = "light" | "dark";
66
88
  type WalrosThemeMode = "body" | "viewport";
67
89
  type WalrosThemeShakeTarget = HTMLElement | RefObject<HTMLElement | null> | null | undefined;
@@ -107,5 +129,7 @@ declare const walrosLogoChromeUrl: string;
107
129
  declare const walrosWordmarkLightUrl: string;
108
130
  declare const walrosWordmarkDarkUrl: string;
109
131
  declare const walrosThemeGlitchSoundUrl: string;
132
+ declare const walrosSeasonalPumpkinUrl: string;
133
+ declare const walrosSeasonalHeartArrowUrl: string;
110
134
 
111
- export { DirectionalCursor, type PortalOrigin, type UseWalrosThemeOptions, type UseWalrosThemeResult, Walros3DPortalTransition, type Walros3DPortalTransitionProps, WalrosLogo, type WalrosLogoProps, WalrosPortalTransition, type WalrosPortalTransitionProps, type WalrosTheme, WalrosThemeGlitch, type WalrosThemeGlitchProps, type WalrosThemeMode, type WalrosThemeShakeTarget, WalrosThemeTransition, type WalrosThemeTransitionProps, WalrosWordmark, type WalrosWordmarkProps, useWalrosTheme, walrosLogoChromeUrl, walrosPortalSilhouetteUrl, walrosThemeGlitchSoundUrl, walrosWordmarkDarkUrl, walrosWordmarkLightUrl };
135
+ export { DirectionalCursor, type PortalOrigin, type UseWalrosThemeOptions, type UseWalrosThemeResult, Walros3DPortalTransition, type Walros3DPortalTransitionProps, WalrosLogo, type WalrosLogoProps, WalrosPortalTransition, type WalrosPortalTransitionProps, type WalrosSeason, WalrosSeasonalBackground, type WalrosSeasonalBackgroundProps, type WalrosTheme, WalrosThemeGlitch, type WalrosThemeGlitchProps, type WalrosThemeMode, type WalrosThemeShakeTarget, WalrosThemeTransition, type WalrosThemeTransitionProps, WalrosWordmark, type WalrosWordmarkProps, getWalrosSeason, useWalrosTheme, walrosLogoChromeUrl, walrosPortalSilhouetteUrl, walrosSeasonalHeartArrowUrl, walrosSeasonalPumpkinUrl, walrosThemeGlitchSoundUrl, walrosWordmarkDarkUrl, walrosWordmarkLightUrl };
package/dist/index.js CHANGED
@@ -362,21 +362,21 @@ var walrosHandCursor = "data:image/x-icon;base64,AAACAAEAICAAAAYAAQCoEAAAFgAAACg
362
362
  import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
363
363
  var DESKTOP_CURSOR_QUERY = "(min-width: 1024px) and (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference)";
364
364
  var CURSOR_STYLES = `
365
- .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; }
365
+ .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; }
366
366
  .directional-cursor.is-visible { opacity: 1; }
367
367
  .directional-cursor-shape { width: 20px; height: 22px; transform-origin: center center; will-change: transform; }
368
368
  .directional-cursor svg { display: block; width: 20px; height: 22px; }
369
+ .directional-cursor-hand { display: none; position: absolute; top: 0; left: 0; width: 32px; height: 32px; transform: translate(-8px, -2px); image-rendering: auto; }
370
+ .directional-cursor.is-hand .directional-cursor-shape { display: none; }
371
+ .directional-cursor.is-hand .directional-cursor-hand { display: block; }
369
372
  @media (min-width: 1024px) and (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
370
373
  html.has-directional-cursor, html.has-directional-cursor * { cursor: none !important; }
371
374
  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"])),
372
375
  html.has-directional-cursor [contenteditable="true"] * { cursor: text !important; }
373
- html.has-directional-cursor :is(a, button, select, summary, [role="button"], [role="link"], [aria-haspopup="true"], input[type="checkbox"], input[type="radio"], input[type="range"]) {
374
- cursor: url("${walrosHandCursor}") 8 2, pointer !important;
375
- }
376
376
  }
377
377
  `;
378
378
  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"])';
379
- var INTERACTIVE_SELECTOR = 'a, button, select, summary, [role="button"], [role="link"], [aria-haspopup="true"], input[type="checkbox"], input[type="radio"], input[type="range"]';
379
+ var INTERACTIVE_SELECTOR = 'a, button, select, summary, label, [role="button"], [role="link"], [role="menuitem"], [role="option"], [role="tab"], [aria-haspopup="true"], [data-cursor-hand], input[type="checkbox"], input[type="radio"], input[type="range"]';
380
380
  function DirectionalCursor() {
381
381
  const positionLayer = useRef2(null);
382
382
  const directionLayer = useRef2(null);
@@ -401,6 +401,13 @@ function DirectionalCursor() {
401
401
  let targetScale = 1;
402
402
  let lastX = currentX;
403
403
  let lastY = 0;
404
+ const updateCursorMode = (eventTarget) => {
405
+ const target = eventTarget instanceof Element ? eventTarget : null;
406
+ const textEntry = target?.closest(TEXT_ENTRY_SELECTOR);
407
+ const interactive = target?.closest(INTERACTIVE_SELECTOR);
408
+ position.classList.toggle("is-visible", !textEntry);
409
+ position.classList.toggle("is-hand", Boolean(interactive && !textEntry));
410
+ };
404
411
  const render = () => {
405
412
  currentX += (targetX - currentX) * 0.4;
406
413
  currentY += (targetY - currentY) * 0.4;
@@ -424,10 +431,7 @@ function DirectionalCursor() {
424
431
  const distance = Math.hypot(deltaX, deltaY);
425
432
  targetX = event.clientX;
426
433
  targetY = event.clientY;
427
- const target = event.target instanceof Element ? event.target : null;
428
- const textEntry = target?.closest(TEXT_ENTRY_SELECTOR);
429
- const interactive = target?.closest(INTERACTIVE_SELECTOR);
430
- position.classList.toggle("is-visible", !textEntry && !interactive);
434
+ updateCursorMode(event.target);
431
435
  if (distance > 1.25) {
432
436
  const rawAngle = Math.atan2(deltaY, deltaX) * (180 / Math.PI) + 90;
433
437
  const normalizedAngle = (rawAngle % 360 + 360) % 360;
@@ -453,18 +457,24 @@ function DirectionalCursor() {
453
457
  latestEvent = event;
454
458
  if (!moveFrame) moveFrame = window.requestAnimationFrame(processMove);
455
459
  };
460
+ const handleMouseOver = (event) => {
461
+ updateCursorMode(event.target);
462
+ };
456
463
  const activate = () => {
457
464
  if (active) return;
458
465
  active = true;
459
466
  document.documentElement.classList.add("has-directional-cursor");
460
467
  window.addEventListener("mousemove", handleMouseMove, { passive: true });
468
+ window.addEventListener("mouseover", handleMouseOver, { passive: true });
461
469
  };
462
470
  const deactivate = () => {
463
471
  if (!active) return;
464
472
  active = false;
465
473
  document.documentElement.classList.remove("has-directional-cursor");
466
474
  position.classList.remove("is-visible");
475
+ position.classList.remove("is-hand");
467
476
  window.removeEventListener("mousemove", handleMouseMove);
477
+ window.removeEventListener("mouseover", handleMouseOver);
468
478
  window.cancelAnimationFrame(frame);
469
479
  window.cancelAnimationFrame(moveFrame);
470
480
  window.clearTimeout(scaleTimer);
@@ -484,22 +494,25 @@ function DirectionalCursor() {
484
494
  }, []);
485
495
  return /* @__PURE__ */ jsxs3(Fragment2, { children: [
486
496
  /* @__PURE__ */ jsx5("style", { children: CURSOR_STYLES }),
487
- /* @__PURE__ */ jsx5("div", { ref: positionLayer, className: "directional-cursor", "aria-hidden": "true", children: /* @__PURE__ */ jsx5("div", { ref: directionLayer, className: "directional-cursor-shape", children: /* @__PURE__ */ jsxs3("svg", { width: "50", height: "54", viewBox: "0 0 50 54", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
488
- /* @__PURE__ */ jsxs3("g", { filter: "url(#walros-cursor-shadow)", children: [
489
- /* @__PURE__ */ jsx5("path", { d: "M42.6817 41.1495L27.5103 6.79925C26.7269 5.02557 24.2082 5.02558 23.3927 6.79925L7.59814 41.1495C6.75833 42.9759 8.52712 44.8902 10.4125 44.1954L24.3757 39.0496C24.8829 38.8627 25.4385 38.8627 25.9422 39.0496L39.8121 44.1954C41.6849 44.8902 43.4884 42.9759 42.6817 41.1495Z", fill: "black" }),
490
- /* @__PURE__ */ jsx5("path", { d: "M43.7146 40.6933L28.5431 6.34306C27.3556 3.65428 23.5772 3.69516 22.3668 6.32755L6.57226 40.6778C5.3134 43.4156 7.97238 46.298 10.803 45.2549L24.7662 40.109C25.0221 40.0147 25.2999 40.0156 25.5494 40.1082L39.4193 45.254C42.2261 46.2953 44.9254 43.4347 43.7146 40.6933Z", stroke: "white", strokeWidth: "2.25825" })
491
- ] }),
492
- /* @__PURE__ */ jsx5("defs", { children: /* @__PURE__ */ jsxs3("filter", { id: "walros-cursor-shadow", x: "0.602397", y: "0.952444", width: "49.0584", height: "52.428", filterUnits: "userSpaceOnUse", colorInterpolationFilters: "sRGB", children: [
493
- /* @__PURE__ */ jsx5("feFlood", { floodOpacity: "0", result: "BackgroundImageFix" }),
494
- /* @__PURE__ */ jsx5("feColorMatrix", { in: "SourceAlpha", type: "matrix", values: "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0", result: "hardAlpha" }),
495
- /* @__PURE__ */ jsx5("feOffset", { dy: "2.25825" }),
496
- /* @__PURE__ */ jsx5("feGaussianBlur", { stdDeviation: "2.25825" }),
497
- /* @__PURE__ */ jsx5("feComposite", { in2: "hardAlpha", operator: "out" }),
498
- /* @__PURE__ */ jsx5("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" }),
499
- /* @__PURE__ */ jsx5("feBlend", { mode: "normal", in2: "BackgroundImageFix", result: "effect1_dropShadow" }),
500
- /* @__PURE__ */ jsx5("feBlend", { mode: "normal", in: "SourceGraphic", in2: "effect1_dropShadow", result: "shape" })
501
- ] }) })
502
- ] }) }) })
497
+ /* @__PURE__ */ jsxs3("div", { ref: positionLayer, className: "directional-cursor", "aria-hidden": "true", children: [
498
+ /* @__PURE__ */ jsx5("div", { ref: directionLayer, className: "directional-cursor-shape", children: /* @__PURE__ */ jsxs3("svg", { width: "50", height: "54", viewBox: "0 0 50 54", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
499
+ /* @__PURE__ */ jsxs3("g", { filter: "url(#walros-cursor-shadow)", children: [
500
+ /* @__PURE__ */ jsx5("path", { d: "M42.6817 41.1495L27.5103 6.79925C26.7269 5.02557 24.2082 5.02558 23.3927 6.79925L7.59814 41.1495C6.75833 42.9759 8.52712 44.8902 10.4125 44.1954L24.3757 39.0496C24.8829 38.8627 25.4385 38.8627 25.9422 39.0496L39.8121 44.1954C41.6849 44.8902 43.4884 42.9759 42.6817 41.1495Z", fill: "black" }),
501
+ /* @__PURE__ */ jsx5("path", { d: "M43.7146 40.6933L28.5431 6.34306C27.3556 3.65428 23.5772 3.69516 22.3668 6.32755L6.57226 40.6778C5.3134 43.4156 7.97238 46.298 10.803 45.2549L24.7662 40.109C25.0221 40.0147 25.2999 40.0156 25.5494 40.1082L39.4193 45.254C42.2261 46.2953 44.9254 43.4347 43.7146 40.6933Z", stroke: "white", strokeWidth: "2.25825" })
502
+ ] }),
503
+ /* @__PURE__ */ jsx5("defs", { children: /* @__PURE__ */ jsxs3("filter", { id: "walros-cursor-shadow", x: "0.602397", y: "0.952444", width: "49.0584", height: "52.428", filterUnits: "userSpaceOnUse", colorInterpolationFilters: "sRGB", children: [
504
+ /* @__PURE__ */ jsx5("feFlood", { floodOpacity: "0", result: "BackgroundImageFix" }),
505
+ /* @__PURE__ */ jsx5("feColorMatrix", { in: "SourceAlpha", type: "matrix", values: "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0", result: "hardAlpha" }),
506
+ /* @__PURE__ */ jsx5("feOffset", { dy: "2.25825" }),
507
+ /* @__PURE__ */ jsx5("feGaussianBlur", { stdDeviation: "2.25825" }),
508
+ /* @__PURE__ */ jsx5("feComposite", { in2: "hardAlpha", operator: "out" }),
509
+ /* @__PURE__ */ jsx5("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" }),
510
+ /* @__PURE__ */ jsx5("feBlend", { mode: "normal", in2: "BackgroundImageFix", result: "effect1_dropShadow" }),
511
+ /* @__PURE__ */ jsx5("feBlend", { mode: "normal", in: "SourceGraphic", in2: "effect1_dropShadow", result: "shape" })
512
+ ] }) })
513
+ ] }) }),
514
+ /* @__PURE__ */ jsx5("img", { className: "directional-cursor-hand", src: walrosHandCursor, alt: "" })
515
+ ] })
503
516
  ] });
504
517
  }
505
518
 
@@ -524,6 +537,14 @@ var walrosThemeGlitchSoundUrl = new URL(
524
537
  "./assets/walros-theme-glitch.mp3",
525
538
  import.meta.url
526
539
  ).href;
540
+ var walrosSeasonalPumpkinUrl = new URL(
541
+ "./assets/walros-seasonal-pumpkin.svg",
542
+ import.meta.url
543
+ ).href;
544
+ var walrosSeasonalHeartArrowUrl = new URL(
545
+ "./assets/walros-seasonal-heart-arrow.svg",
546
+ import.meta.url
547
+ ).href;
527
548
 
528
549
  // src/components/WalrosLogo.tsx
529
550
  import { jsx as jsx6 } from "react/jsx-runtime";
@@ -563,12 +584,247 @@ function WalrosWordmark({
563
584
  );
564
585
  }
565
586
 
587
+ // src/components/WalrosSeasonalBackground.tsx
588
+ import { useEffect as useEffect2, useMemo, useState as useState4 } from "react";
589
+ import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
590
+ var PARTICLES = [
591
+ [2, 6, 0, 28, -18, 0.84],
592
+ [10, 25, 2.2, 31, 16, 0.72],
593
+ [18, 58, 4.6, 29, -14, 0.8],
594
+ [26, 12, 6.9, 33, 20, 0.75],
595
+ [34, 42, 9.3, 27, -16, 0.86],
596
+ [42, 79, 11.8, 32, 18, 0.72],
597
+ [50, 3, 14.1, 30, -20, 0.82],
598
+ [58, 28, 16.7, 34, 15, 0.7],
599
+ [66, 63, 19.2, 28, -18, 0.84],
600
+ [74, 16, 21.5, 31, 16, 0.74],
601
+ [82, 48, 24.1, 29, -14, 0.8],
602
+ [90, 84, 26.8, 33, 20, 0.7],
603
+ [97, 36, 29.4, 27, -16, 0.86],
604
+ [13, 91, 31.8, 32, 18, 0.73],
605
+ [54, 94, 34.3, 30, -20, 0.8],
606
+ [88, 68, 37.1, 34, 15, 0.7],
607
+ [6, 23, 3.8, 35, -15, 0.8],
608
+ [21, 71, 7.1, 30, 18, 0.8],
609
+ [39, 32, 10.6, 33, -18, 0.8],
610
+ [47, 87, 13.2, 29, 16, 0.8],
611
+ [61, 53, 16.8, 35, -16, 0.8],
612
+ [73, 9, 20.3, 30, 18, 0.8],
613
+ [84, 76, 23.9, 33, -18, 0.8],
614
+ [95, 57, 27.5, 29, 16, 0.8]
615
+ ];
616
+ var STYLES = `
617
+ .walros-seasonal-background {
618
+ position: relative;
619
+ isolation: isolate;
620
+ min-height: 100dvh;
621
+ }
622
+ .walros-seasonal-background__decorations {
623
+ position: absolute;
624
+ inset: 0;
625
+ z-index: 0;
626
+ overflow: hidden;
627
+ pointer-events: none;
628
+ contain: layout paint;
629
+ }
630
+ .walros-seasonal-background__content {
631
+ position: relative;
632
+ z-index: 1;
633
+ }
634
+ .walros-seasonal-background__particle {
635
+ position: absolute;
636
+ top: var(--walros-seasonal-top);
637
+ left: 0;
638
+ display: block;
639
+ width: clamp(24px, 2.45vw, 44px);
640
+ height: clamp(24px, 2.45vw, 44px);
641
+ color: var(--walros-seasonal-color);
642
+ /* Important prevents external theme styles or animations from making
643
+ individual decorations fade at different moments. */
644
+ opacity: var(--walros-seasonal-opacity) !important;
645
+ filter: drop-shadow(0 2px 5px rgb(0 0 0 / .12));
646
+ animation: walros-seasonal-drift var(--walros-seasonal-duration) linear var(--walros-seasonal-delay) infinite;
647
+ will-change: transform;
648
+ }
649
+ .walros-seasonal-background__particle svg {
650
+ display: block;
651
+ width: 100%;
652
+ height: 100%;
653
+ overflow: visible;
654
+ }
655
+ @keyframes walros-seasonal-drift {
656
+ 0% { transform: translate3d(-12vw, 0, 0) rotate(-12deg); }
657
+ 50% { transform: translate3d(50vw, var(--walros-seasonal-sway), 0) rotate(180deg); }
658
+ 100% { transform: translate3d(112vw, 0, 0) rotate(372deg); }
659
+ }
660
+ @media (prefers-reduced-motion: reduce) {
661
+ .walros-seasonal-background__particle {
662
+ animation: none;
663
+ opacity: var(--walros-seasonal-opacity);
664
+ transform: translate3d(0, 0, 0);
665
+ }
666
+ }
667
+ `;
668
+ function classNames(...values) {
669
+ return values.filter(Boolean).join(" ");
670
+ }
671
+ function installStyles() {
672
+ if (typeof document === "undefined" || document.getElementById("walros-seasonal-background-styles")) return;
673
+ const style = document.createElement("style");
674
+ style.id = "walros-seasonal-background-styles";
675
+ style.textContent = STYLES;
676
+ document.head.appendChild(style);
677
+ }
678
+ function getDateParts(date, timeZone) {
679
+ const parts = new Intl.DateTimeFormat("en-GB", {
680
+ timeZone,
681
+ day: "2-digit",
682
+ month: "2-digit",
683
+ year: "numeric"
684
+ }).formatToParts(date);
685
+ const value = (type) => Number(parts.find((part) => part.type === type)?.value);
686
+ return { day: value("day"), month: value("month"), year: value("year") };
687
+ }
688
+ function getUtcOffsetMilliseconds(date, timeZone) {
689
+ const parts = new Intl.DateTimeFormat("en-GB", {
690
+ timeZone,
691
+ timeZoneName: "longOffset"
692
+ }).formatToParts(date);
693
+ const offset = parts.find((part) => part.type === "timeZoneName")?.value ?? "GMT";
694
+ const match = offset.match(/^GMT([+-])(\d{2}):(\d{2})$/);
695
+ if (!match) return 0;
696
+ const minutes = Number(match[2]) * 60 + Number(match[3]);
697
+ return (match[1] === "+" ? 1 : -1) * minutes * 6e4;
698
+ }
699
+ function millisecondsUntilNextMidnight(timeZone) {
700
+ const now = /* @__PURE__ */ new Date();
701
+ const { year, month, day } = getDateParts(now, timeZone);
702
+ const localNextMidnight = Date.UTC(year, month - 1, day + 1, 0, 0, 1);
703
+ let nextMidnight = localNextMidnight - getUtcOffsetMilliseconds(new Date(localNextMidnight), timeZone);
704
+ nextMidnight = localNextMidnight - getUtcOffsetMilliseconds(new Date(nextMidnight), timeZone);
705
+ return Math.max(1e3, nextMidnight - now.getTime());
706
+ }
707
+ function getWalrosSeason(date = /* @__PURE__ */ new Date(), timeZone = "Europe/Madrid") {
708
+ const { day, month } = getDateParts(date, timeZone);
709
+ if (month === 9 && day >= 30 || month === 10) return "halloween";
710
+ if (month === 11 && day >= 30 || month === 12 || month === 1 && day <= 10) return "winter";
711
+ if (month === 2 && day === 14) return "valentine";
712
+ return null;
713
+ }
714
+ function useAutomaticSeason(timeZone) {
715
+ const [now, setNow] = useState4(() => /* @__PURE__ */ new Date());
716
+ useEffect2(() => {
717
+ let timer = 0;
718
+ const refreshAtNextMidnight = () => {
719
+ timer = window.setTimeout(() => {
720
+ setNow(/* @__PURE__ */ new Date());
721
+ refreshAtNextMidnight();
722
+ }, millisecondsUntilNextMidnight(timeZone));
723
+ };
724
+ refreshAtNextMidnight();
725
+ return () => window.clearTimeout(timer);
726
+ }, [timeZone]);
727
+ return getWalrosSeason(now, timeZone);
728
+ }
729
+ function SnowIcon() {
730
+ return /* @__PURE__ */ jsx8("svg", { viewBox: "0 0 32 32", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsxs4("g", { stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: [
731
+ /* @__PURE__ */ jsx8("path", { d: "M16 3v26M4.7 9.5l22.6 13M4.7 22.5l22.6-13" }),
732
+ /* @__PURE__ */ jsx8("path", { d: "m16 3-3 4M16 3l3 4M16 29l-3-4M16 29l3-4M4.7 9.5l4.9.5M4.7 9.5l2 4.5M27.3 22.5l-4.9-.5M27.3 22.5l-2-4.5M4.7 22.5l4.9-.5M4.7 22.5l2-4.5M27.3 9.5l-4.9.5M27.3 9.5l-2 4.5" })
733
+ ] }) });
734
+ }
735
+ function PumpkinIcon() {
736
+ return /* @__PURE__ */ jsxs4("svg", { viewBox: "0 0 160 160", fill: "none", "aria-hidden": "true", children: [
737
+ /* @__PURE__ */ jsxs4("defs", { children: [
738
+ /* @__PURE__ */ jsxs4("linearGradient", { id: "walros-seasonal-pumpkin", x1: "28", y1: "44", x2: "133", y2: "132", gradientUnits: "userSpaceOnUse", children: [
739
+ /* @__PURE__ */ jsx8("stop", { stopColor: "#FF9F17" }),
740
+ /* @__PURE__ */ jsx8("stop", { offset: "1", stopColor: "#F06408" })
741
+ ] }),
742
+ /* @__PURE__ */ jsxs4("linearGradient", { id: "walros-seasonal-stem", x1: "83", y1: "15", x2: "105", y2: "55", gradientUnits: "userSpaceOnUse", children: [
743
+ /* @__PURE__ */ jsx8("stop", { stopColor: "#45933D" }),
744
+ /* @__PURE__ */ jsx8("stop", { offset: "1", stopColor: "#1D642C" })
745
+ ] })
746
+ ] }),
747
+ /* @__PURE__ */ jsx8("path", { d: "M88 45c-2-14 3-26 14-34 11 7 17 17 16 31-1 8-5 13-12 15-8 3-15-2-18-12Z", fill: "url(#walros-seasonal-stem)" }),
748
+ /* @__PURE__ */ jsx8("path", { d: "M80 36c-36 0-61 22-61 57 0 34 24 53 61 53s61-19 61-53c0-35-25-57-61-57Z", fill: "url(#walros-seasonal-pumpkin)" }),
749
+ /* @__PURE__ */ jsx8("path", { d: "M80 38c-18 14-23 75 0 106M51 44c-17 22-17 64 0 94M109 44c17 22 17 64 0 94", stroke: "#FFBE3C", strokeWidth: "5", strokeLinecap: "round", opacity: ".6" }),
750
+ /* @__PURE__ */ jsx8("path", { d: "m47 82 16-20c2-3 6-3 8 1l8 24c1 4-3 7-7 6l-22-4c-4-1-5-4-3-7ZM113 82 97 62c-2-3-6-3-8 1l-8 24c-1 4 3 7 7 6l22-4c4-1 5-4 3-7ZM78 91l-10 12c-3 3-1 8 4 8h17c5 0 7-5 4-8L83 91c-1-2-4-2-5 0Z", fill: "#3A260F" }),
751
+ /* @__PURE__ */ jsx8("path", { d: "M45 112c-2-5 4-8 8-5l10 7 10-7c2-2 5-2 7 0l10 7 10-7c4-3 10 0 8 5l-9 28c-1 4-5 5-8 3l-11-8-11 8c-3 2-7 1-8-3l-16-28Z", fill: "#3A260F" })
752
+ ] });
753
+ }
754
+ function HeartArrowIcon() {
755
+ return /* @__PURE__ */ jsxs4("svg", { viewBox: "0 0 160 160", fill: "none", "aria-hidden": "true", children: [
756
+ /* @__PURE__ */ jsxs4("defs", { children: [
757
+ /* @__PURE__ */ jsxs4("linearGradient", { id: "walros-seasonal-heart", x1: "40", y1: "51", x2: "123", y2: "129", gradientUnits: "userSpaceOnUse", children: [
758
+ /* @__PURE__ */ jsx8("stop", { stopColor: "#FF5457" }),
759
+ /* @__PURE__ */ jsx8("stop", { offset: "1", stopColor: "#D41E32" })
760
+ ] }),
761
+ /* @__PURE__ */ jsxs4("linearGradient", { id: "walros-seasonal-gold", x1: "24", y1: "24", x2: "135", y2: "133", gradientUnits: "userSpaceOnUse", children: [
762
+ /* @__PURE__ */ jsx8("stop", { stopColor: "#FFE958" }),
763
+ /* @__PURE__ */ jsx8("stop", { offset: "1", stopColor: "#F3AE19" })
764
+ ] })
765
+ ] }),
766
+ /* @__PURE__ */ jsx8("path", { d: "M80 137S28 107 28 64c0-20 14-34 33-34 10 0 16 5 19 12 3-7 9-12 19-12 19 0 33 14 33 34 0 43-52 73-52 73Z", fill: "url(#walros-seasonal-heart)", stroke: "#C92735", strokeWidth: "7", strokeLinejoin: "round" }),
767
+ /* @__PURE__ */ jsx8("path", { d: "M76 44c-13-9-28-2-33 12", stroke: "#FF9A90", strokeWidth: "6", strokeLinecap: "round", opacity: ".45" }),
768
+ /* @__PURE__ */ jsx8("path", { d: "m18 43 37-16-16 37-21-21ZM142 117l-37 16 16-37 21 21Z", fill: "url(#walros-seasonal-gold)", stroke: "#D8A91C", strokeWidth: "5", strokeLinejoin: "round" }),
769
+ /* @__PURE__ */ jsx8("path", { d: "m31 53 96 72", stroke: "#F5B415", strokeWidth: "13", strokeLinecap: "round" }),
770
+ /* @__PURE__ */ jsx8("path", { d: "M72 89c0-16 11-24 24-22", stroke: "#AE1830", strokeWidth: "9", strokeLinecap: "round" })
771
+ ] });
772
+ }
773
+ function Decoration({ season }) {
774
+ if (season === "halloween") return /* @__PURE__ */ jsx8(PumpkinIcon, {});
775
+ if (season === "winter") return /* @__PURE__ */ jsx8(SnowIcon, {});
776
+ return /* @__PURE__ */ jsx8(HeartArrowIcon, {});
777
+ }
778
+ function getSeasonColor(season) {
779
+ if (season === "halloween") return "transparent";
780
+ if (season === "winter") return "#78B7E8";
781
+ return "transparent";
782
+ }
783
+ function WalrosSeasonalBackground({
784
+ children,
785
+ season = "auto",
786
+ timeZone = "Europe/Madrid",
787
+ density = 20,
788
+ enabled = true,
789
+ className,
790
+ contentClassName,
791
+ style
792
+ }) {
793
+ useEffect2(() => installStyles(), []);
794
+ const automaticSeason = useAutomaticSeason(timeZone);
795
+ const activeSeason = season === "auto" ? automaticSeason : season === "none" ? null : season;
796
+ const particleCount = Math.max(1, Math.min(PARTICLES.length, Math.round(density)));
797
+ const particles = useMemo(() => PARTICLES.slice(0, particleCount), [particleCount]);
798
+ return /* @__PURE__ */ jsxs4("div", { className: classNames("walros-seasonal-background", className), style, children: [
799
+ enabled && activeSeason && /* @__PURE__ */ jsx8("div", { className: "walros-seasonal-background__decorations", "aria-hidden": "true", children: particles.map(([, top, , duration, sway], index) => {
800
+ const elapsed = index / particleCount * duration;
801
+ return /* @__PURE__ */ jsx8(
802
+ "span",
803
+ {
804
+ className: "walros-seasonal-background__particle",
805
+ style: {
806
+ "--walros-seasonal-top": `${top}%`,
807
+ "--walros-seasonal-delay": `-${elapsed}s`,
808
+ "--walros-seasonal-duration": `${duration}s`,
809
+ "--walros-seasonal-sway": `${sway}px`,
810
+ "--walros-seasonal-opacity": ".52",
811
+ "--walros-seasonal-color": getSeasonColor(activeSeason)
812
+ },
813
+ children: /* @__PURE__ */ jsx8(Decoration, { season: activeSeason })
814
+ },
815
+ `${activeSeason}-${index}`
816
+ );
817
+ }) }),
818
+ /* @__PURE__ */ jsx8("div", { className: classNames("walros-seasonal-background__content", contentClassName), children })
819
+ ] });
820
+ }
821
+
566
822
  // src/hooks/useWalrosTheme.ts
567
823
  import {
568
824
  useCallback,
569
- useEffect as useEffect2,
825
+ useEffect as useEffect3,
570
826
  useRef as useRef3,
571
- useState as useState4
827
+ useState as useState5
572
828
  } from "react";
573
829
  var GLITCH_BASE_CLASS = "walros-theme-glitch-page";
574
830
  var GLITCH_BODY_CLASS = "walros-theme-glitch-page--body";
@@ -615,11 +871,11 @@ function useWalrosTheme({
615
871
  lockScroll,
616
872
  onAfterUnlock
617
873
  } = {}) {
618
- const [theme, setThemeState] = useState4(
874
+ const [theme, setThemeState] = useState5(
619
875
  () => readInitialTheme(storageKey, defaultTheme, useSystemPreference)
620
876
  );
621
- const [mounted, setMounted] = useState4(false);
622
- const [glitching, setGlitching] = useState4(false);
877
+ const [mounted, setMounted] = useState5(false);
878
+ const [glitching, setGlitching] = useState5(false);
623
879
  const themeRef = useRef3(theme);
624
880
  const glitchingRef = useRef3(false);
625
881
  const swapTimerRef = useRef3(null);
@@ -674,7 +930,7 @@ function useWalrosTheme({
674
930
  },
675
931
  [storageKey]
676
932
  );
677
- useEffect2(() => {
933
+ useEffect3(() => {
678
934
  const initialTheme = readInitialTheme(
679
935
  storageKey,
680
936
  defaultTheme,
@@ -809,7 +1065,7 @@ function useWalrosTheme({
809
1065
  finishGlitch();
810
1066
  }, effectiveDuration);
811
1067
  }, [finishGlitch, lockViewport, persistTheme, playThemeSound, swapDelay, totalDuration]);
812
- useEffect2(() => {
1068
+ useEffect3(() => {
813
1069
  return () => {
814
1070
  clearTimers();
815
1071
  removeShakeClasses();
@@ -834,12 +1090,16 @@ export {
834
1090
  Walros3DPortalTransition,
835
1091
  WalrosLogo,
836
1092
  WalrosPortalTransition,
1093
+ WalrosSeasonalBackground,
837
1094
  WalrosThemeGlitch,
838
1095
  WalrosThemeTransition,
839
1096
  WalrosWordmark,
1097
+ getWalrosSeason,
840
1098
  useWalrosTheme,
841
1099
  walrosLogoChromeUrl,
842
1100
  walrosPortalSilhouetteUrl,
1101
+ walrosSeasonalHeartArrowUrl,
1102
+ walrosSeasonalPumpkinUrl,
843
1103
  walrosThemeGlitchSoundUrl,
844
1104
  walrosWordmarkDarkUrl,
845
1105
  walrosWordmarkLightUrl
package/dist/index.js.map CHANGED
@@ -1 +1 @@
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/handCursor.ts","../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\nexport type PortalOrigin = { centerX: number; centerY: number; width: number; height: number };\n\nexport type Walros3DPortalTransitionProps = {\n origin: PortalOrigin;\n onComplete?: () => void;\n duration?: number;\n backgroundColor?: string;\n zIndex?: number;\n lockScroll?: boolean;\n};\n\nconst SILHOUETTE_VIEWBOX = 1254;\nconst FOCUS_X = 626;\nconst FOCUS_Y = 333;\nconst PORTAL_RADIUS = 190;\n\n/** The stable portal used by ui 0.3.4: a centred silhouette that only scales. */\nexport function Walros3DPortalTransition({\n onComplete,\n duration = 900,\n backgroundColor = \"#000\",\n zIndex = 10001,\n lockScroll = true,\n}: Walros3DPortalTransitionProps) {\n const [visible, setVisible] = useState(true);\n const [viewport] = 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 maskScale = useRef<SVGGElement>(null);\n const completeRef = useRef(onComplete);\n completeRef.current = onComplete;\n const maskId = `walros-portal-mask-${useId().replace(/:/g, \"_\")}`;\n\n useLayoutEffect(() => {\n if (!visible || viewport.width <= 0 || viewport.height <= 0 || !overlay.current || !maskScale.current) return;\n const previousOverflow = document.body.style.overflow;\n if (lockScroll) document.body.style.overflow = \"hidden\";\n\n const initialPixels = Math.min(180, Math.max(120, viewport.width * 0.12));\n const initialScale = initialPixels / SILHOUETTE_VIEWBOX;\n const finalScale = (Math.hypot(viewport.width, viewport.height) / 2 + 80) / PORTAL_RADIUS * 1.15;\n const visualCenter = SILHOUETTE_VIEWBOX / 2;\n const portalCenterX = viewport.width / 2 - (visualCenter - FOCUS_X) * initialScale;\n const portalCenterY = viewport.height / 2 - (visualCenter - FOCUS_Y) * initialScale;\n const total = duration / 1000;\n\n gsap.set(maskScale.current, { scale: initialScale, svgOrigin: \"0 0\" });\n gsap.set(overlay.current, { opacity: 1 });\n const finish = () => {\n if (lockScroll) document.body.style.overflow = previousOverflow;\n setVisible(false);\n completeRef.current?.();\n };\n const timeline = gsap.timeline({ onComplete: finish });\n if (window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches) {\n timeline.to(overlay.current, { opacity: 0, duration: 0.15, ease: \"power1.out\" });\n } else {\n timeline\n .to(maskScale.current, { scale: initialScale * 1.4, duration: total * 0.15, ease: \"power2.out\" }, 0)\n .to(maskScale.current, { scale: finalScale, duration: total * 0.85, ease: \"power2.in\" }, total * 0.15)\n .to(overlay.current, { opacity: 0, duration: total * 0.1, ease: \"power2.out\" }, total * 0.9);\n }\n return () => {\n timeline.kill();\n if (lockScroll) document.body.style.overflow = previousOverflow;\n };\n }, [duration, lockScroll, viewport, visible]);\n\n if (!visible) return null;\n const initialPixels = Math.min(180, Math.max(120, viewport.width * 0.12));\n const initialScale = initialPixels / SILHOUETTE_VIEWBOX;\n const visualCenter = SILHOUETTE_VIEWBOX / 2;\n const portalCenterX = viewport.width / 2 - (visualCenter - FOCUS_X) * initialScale;\n const portalCenterY = viewport.height / 2 - (visualCenter - FOCUS_Y) * initialScale;\n\n return <div ref={overlay} className=\"walros-3d-portal\" aria-hidden=\"true\" style={{ position: \"fixed\", inset: 0, width: \"100vw\", height: \"100dvh\", overflow: \"hidden\", pointerEvents: \"none\", zIndex, backgroundColor: viewport.width > 0 ? \"transparent\" : backgroundColor }}>\n <svg width=\"100%\" height=\"100%\" viewBox={`0 0 ${viewport.width} ${viewport.height}`} preserveAspectRatio=\"none\" style={{ display: \"block\"}}>\n <defs><mask id={maskId} maskUnits=\"userSpaceOnUse\" x=\"0\" y=\"0\" width={viewport.width} height={viewport.height}>\n <rect width={viewport.width} height={viewport.height} fill=\"white\" />\n <g transform={`translate(${portalCenterX} ${portalCenterY})`}>\n <g ref={maskScale} transform={`scale(${initialScale})`}>\n <g transform={`translate(${-FOCUS_X} ${-FOCUS_Y})`} fill=\"black\">\n {walrosPortalPaths.map((path, index) => <path d={path} key={index} />)}\n </g>\n </g>\n </g>\n </mask></defs>\n <rect width={viewport.width} height={viewport.height} fill={backgroundColor} mask={`url(#${maskId})`} />\n </svg>\n </div>;\n}\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\";\nimport { walrosHandCursor } from \"../handCursor\";\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 html.has-directional-cursor :is(a, button, select, summary, [role=\"button\"], [role=\"link\"], [aria-haspopup=\"true\"], input[type=\"checkbox\"], input[type=\"radio\"], input[type=\"range\"]) {\n cursor: url(\"${walrosHandCursor}\") 8 2, pointer !important;\n }\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\"])';\nconst INTERACTIVE_SELECTOR = 'a, button, select, summary, [role=\"button\"], [role=\"link\"], [aria-haspopup=\"true\"], input[type=\"checkbox\"], input[type=\"radio\"], input[type=\"range\"]';\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 target = event.target instanceof Element ? event.target : null;\n const textEntry = target?.closest(TEXT_ENTRY_SELECTOR);\n const interactive = target?.closest(INTERACTIVE_SELECTOR);\n // Interactive controls use the supplied .cur hand. Hide the directional\n // cursor there so two pointers are never shown at once.\n position.classList.toggle(\"is-visible\", !textEntry && !interactive);\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","// Embedded so consumers receive the exact .cur without copying a package asset.\nexport const walrosHandCursor = \"data:image/x-icon;base64,AAACAAEAICAAAAYAAQCoEAAAFgAAACgAAAAgAAAAQAAAAAEAIAAAAAAAgBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA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\";\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?.remove();\n soundRef.current = new Audio(soundUrlRef.current);\n soundRef.current.preload = \"auto\";\n soundRef.current.setAttribute(\"aria-hidden\", \"true\");\n soundRef.current.style.display = \"none\";\n document.body.appendChild(soundRef.current);\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 soundRef.current?.remove();\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","initialPixels","initialScale","visualCenter","portalCenterX","portalCenterY","useLayoutEffect","useState","jsx","useState","createPortal","jsx","jsxs","jsx","createPortal","useRef","Fragment","jsx","jsxs","useRef","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/handCursor.ts","../src/assets.ts","../src/components/WalrosLogo.tsx","../src/components/WalrosWordmark.tsx","../src/components/WalrosSeasonalBackground.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\nexport type PortalOrigin = { centerX: number; centerY: number; width: number; height: number };\n\nexport type Walros3DPortalTransitionProps = {\n origin: PortalOrigin;\n onComplete?: () => void;\n duration?: number;\n backgroundColor?: string;\n zIndex?: number;\n lockScroll?: boolean;\n};\n\nconst SILHOUETTE_VIEWBOX = 1254;\nconst FOCUS_X = 626;\nconst FOCUS_Y = 333;\nconst PORTAL_RADIUS = 190;\n\n/** The stable portal used by ui 0.3.4: a centred silhouette that only scales. */\nexport function Walros3DPortalTransition({\n onComplete,\n duration = 900,\n backgroundColor = \"#000\",\n zIndex = 10001,\n lockScroll = true,\n}: Walros3DPortalTransitionProps) {\n const [visible, setVisible] = useState(true);\n const [viewport] = 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 maskScale = useRef<SVGGElement>(null);\n const completeRef = useRef(onComplete);\n completeRef.current = onComplete;\n const maskId = `walros-portal-mask-${useId().replace(/:/g, \"_\")}`;\n\n useLayoutEffect(() => {\n if (!visible || viewport.width <= 0 || viewport.height <= 0 || !overlay.current || !maskScale.current) return;\n const previousOverflow = document.body.style.overflow;\n if (lockScroll) document.body.style.overflow = \"hidden\";\n\n const initialPixels = Math.min(180, Math.max(120, viewport.width * 0.12));\n const initialScale = initialPixels / SILHOUETTE_VIEWBOX;\n const finalScale = (Math.hypot(viewport.width, viewport.height) / 2 + 80) / PORTAL_RADIUS * 1.15;\n const visualCenter = SILHOUETTE_VIEWBOX / 2;\n const portalCenterX = viewport.width / 2 - (visualCenter - FOCUS_X) * initialScale;\n const portalCenterY = viewport.height / 2 - (visualCenter - FOCUS_Y) * initialScale;\n const total = duration / 1000;\n\n gsap.set(maskScale.current, { scale: initialScale, svgOrigin: \"0 0\" });\n gsap.set(overlay.current, { opacity: 1 });\n const finish = () => {\n if (lockScroll) document.body.style.overflow = previousOverflow;\n setVisible(false);\n completeRef.current?.();\n };\n const timeline = gsap.timeline({ onComplete: finish });\n if (window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches) {\n timeline.to(overlay.current, { opacity: 0, duration: 0.15, ease: \"power1.out\" });\n } else {\n timeline\n .to(maskScale.current, { scale: initialScale * 1.4, duration: total * 0.15, ease: \"power2.out\" }, 0)\n .to(maskScale.current, { scale: finalScale, duration: total * 0.85, ease: \"power2.in\" }, total * 0.15)\n .to(overlay.current, { opacity: 0, duration: total * 0.1, ease: \"power2.out\" }, total * 0.9);\n }\n return () => {\n timeline.kill();\n if (lockScroll) document.body.style.overflow = previousOverflow;\n };\n }, [duration, lockScroll, viewport, visible]);\n\n if (!visible) return null;\n const initialPixels = Math.min(180, Math.max(120, viewport.width * 0.12));\n const initialScale = initialPixels / SILHOUETTE_VIEWBOX;\n const visualCenter = SILHOUETTE_VIEWBOX / 2;\n const portalCenterX = viewport.width / 2 - (visualCenter - FOCUS_X) * initialScale;\n const portalCenterY = viewport.height / 2 - (visualCenter - FOCUS_Y) * initialScale;\n\n return <div ref={overlay} className=\"walros-3d-portal\" aria-hidden=\"true\" style={{ position: \"fixed\", inset: 0, width: \"100vw\", height: \"100dvh\", overflow: \"hidden\", pointerEvents: \"none\", zIndex, backgroundColor: viewport.width > 0 ? \"transparent\" : backgroundColor }}>\n <svg width=\"100%\" height=\"100%\" viewBox={`0 0 ${viewport.width} ${viewport.height}`} preserveAspectRatio=\"none\" style={{ display: \"block\"}}>\n <defs><mask id={maskId} maskUnits=\"userSpaceOnUse\" x=\"0\" y=\"0\" width={viewport.width} height={viewport.height}>\n <rect width={viewport.width} height={viewport.height} fill=\"white\" />\n <g transform={`translate(${portalCenterX} ${portalCenterY})`}>\n <g ref={maskScale} transform={`scale(${initialScale})`}>\n <g transform={`translate(${-FOCUS_X} ${-FOCUS_Y})`} fill=\"black\">\n {walrosPortalPaths.map((path, index) => <path d={path} key={index} />)}\n </g>\n </g>\n </g>\n </mask></defs>\n <rect width={viewport.width} height={viewport.height} fill={backgroundColor} mask={`url(#${maskId})`} />\n </svg>\n </div>;\n}\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\";\nimport { walrosHandCursor } from \"../handCursor\";\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; }\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.directional-cursor-hand { display: none; position: absolute; top: 0; left: 0; width: 32px; height: 32px; transform: translate(-8px, -2px); image-rendering: auto; }\n.directional-cursor.is-hand .directional-cursor-shape { display: none; }\n.directional-cursor.is-hand .directional-cursor-hand { display: block; }\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\"])';\nconst INTERACTIVE_SELECTOR = 'a, button, select, summary, label, [role=\"button\"], [role=\"link\"], [role=\"menuitem\"], [role=\"option\"], [role=\"tab\"], [aria-haspopup=\"true\"], [data-cursor-hand], input[type=\"checkbox\"], input[type=\"radio\"], input[type=\"range\"]';\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;\n let targetScale = 1;\n let lastX = currentX;\n let lastY = 0;\n\n const updateCursorMode = (eventTarget: EventTarget | null) => {\n const target = eventTarget instanceof Element ? eventTarget : null;\n const textEntry = target?.closest(TEXT_ENTRY_SELECTOR);\n const interactive = target?.closest(INTERACTIVE_SELECTOR);\n\n // Text inputs deliberately preserve the native I-beam. Every other\n // state stays inside this overlay, so an OS pointer never flashes next\n // to the WalrOS cursor while entering a control.\n position.classList.toggle(\"is-visible\", !textEntry);\n position.classList.toggle(\"is-hand\", Boolean(interactive && !textEntry));\n };\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 updateCursorMode(event.target);\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) => {\n latestEvent = event;\n if (!moveFrame) moveFrame = window.requestAnimationFrame(processMove);\n };\n\n const handleMouseOver = (event: MouseEvent) => {\n updateCursorMode(event.target);\n };\n\r\n const activate = () => {\r\n if (active) return;\r\n active = true;\n document.documentElement.classList.add(\"has-directional-cursor\");\n window.addEventListener(\"mousemove\", handleMouseMove, { passive: true });\n window.addEventListener(\"mouseover\", handleMouseOver, { passive: true });\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\");\n position.classList.remove(\"is-hand\");\n window.removeEventListener(\"mousemove\", handleMouseMove);\n window.removeEventListener(\"mouseover\", handleMouseOver);\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\">\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>\n </div>\n <img className=\"directional-cursor-hand\" src={walrosHandCursor} alt=\"\" />\n </div></>\n );\n}\n","// Embedded so consumers receive the exact .cur without copying a package asset.\nexport const walrosHandCursor = \"data:image/x-icon;base64,AAACAAEAICAAAAYAAQCoEAAAFgAAACgAAAAgAAAAQAAAAAEAIAAAAAAAgBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA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\";\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\nexport const walrosSeasonalPumpkinUrl = new URL(\n \"./assets/walros-seasonal-pumpkin.svg\",\n import.meta.url,\n).href;\n\nexport const walrosSeasonalHeartArrowUrl = new URL(\n \"./assets/walros-seasonal-heart-arrow.svg\",\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 { useEffect, useMemo, useState } from \"react\";\nimport type { CSSProperties, ReactNode } from \"react\";\n\nexport type WalrosSeason = \"auto\" | \"none\" | \"halloween\" | \"winter\" | \"valentine\";\n\nexport type WalrosSeasonalBackgroundProps = {\n children: ReactNode;\n /** Uses the seasonal calendar when set to auto. */\n season?: WalrosSeason;\n /** Time zone used by automatic mode. Defaults to Europe/Madrid. */\n timeZone?: string;\n /** Number of decorations distributed throughout the page. Defaults to 20. */\n density?: number;\n enabled?: boolean;\n className?: string;\n contentClassName?: string;\n style?: CSSProperties;\n};\n\ntype ActiveSeason = Exclude<WalrosSeason, \"auto\" | \"none\">;\n\nconst PARTICLES = [\n [2, 6, 0, 28, -18, 0.84], [10, 25, 2.2, 31, 16, 0.72],\n [18, 58, 4.6, 29, -14, 0.8], [26, 12, 6.9, 33, 20, 0.75],\n [34, 42, 9.3, 27, -16, 0.86], [42, 79, 11.8, 32, 18, 0.72],\n [50, 3, 14.1, 30, -20, 0.82], [58, 28, 16.7, 34, 15, 0.7],\n [66, 63, 19.2, 28, -18, 0.84], [74, 16, 21.5, 31, 16, 0.74],\n [82, 48, 24.1, 29, -14, 0.8], [90, 84, 26.8, 33, 20, 0.7],\n [97, 36, 29.4, 27, -16, 0.86], [13, 91, 31.8, 32, 18, 0.73],\n [54, 94, 34.3, 30, -20, 0.8], [88, 68, 37.1, 34, 15, 0.7],\n [6, 23, 3.8, 35, -15, 0.8], [21, 71, 7.1, 30, 18, 0.8],\n [39, 32, 10.6, 33, -18, 0.8], [47, 87, 13.2, 29, 16, 0.8],\n [61, 53, 16.8, 35, -16, 0.8], [73, 9, 20.3, 30, 18, 0.8],\n [84, 76, 23.9, 33, -18, 0.8], [95, 57, 27.5, 29, 16, 0.8],\n] as const;\n\nconst STYLES = `\n.walros-seasonal-background {\n position: relative;\n isolation: isolate;\n min-height: 100dvh;\n}\n.walros-seasonal-background__decorations {\n position: absolute;\n inset: 0;\n z-index: 0;\n overflow: hidden;\n pointer-events: none;\n contain: layout paint;\n}\n.walros-seasonal-background__content {\n position: relative;\n z-index: 1;\n}\n.walros-seasonal-background__particle {\n position: absolute;\n top: var(--walros-seasonal-top);\n left: 0;\n display: block;\n width: clamp(24px, 2.45vw, 44px);\n height: clamp(24px, 2.45vw, 44px);\n color: var(--walros-seasonal-color);\n /* Important prevents external theme styles or animations from making\n individual decorations fade at different moments. */\n opacity: var(--walros-seasonal-opacity) !important;\n filter: drop-shadow(0 2px 5px rgb(0 0 0 / .12));\n animation: walros-seasonal-drift var(--walros-seasonal-duration) linear var(--walros-seasonal-delay) infinite;\n will-change: transform;\n}\n.walros-seasonal-background__particle svg {\n display: block;\n width: 100%;\n height: 100%;\n overflow: visible;\n}\n@keyframes walros-seasonal-drift {\n 0% { transform: translate3d(-12vw, 0, 0) rotate(-12deg); }\n 50% { transform: translate3d(50vw, var(--walros-seasonal-sway), 0) rotate(180deg); }\n 100% { transform: translate3d(112vw, 0, 0) rotate(372deg); }\n}\n@media (prefers-reduced-motion: reduce) {\n .walros-seasonal-background__particle {\n animation: none;\n opacity: var(--walros-seasonal-opacity);\n transform: translate3d(0, 0, 0);\n }\n}\n`;\n\nfunction classNames(...values: Array<string | undefined>) {\n return values.filter(Boolean).join(\" \");\n}\n\nfunction installStyles() {\n if (typeof document === \"undefined\" || document.getElementById(\"walros-seasonal-background-styles\")) return;\n const style = document.createElement(\"style\");\n style.id = \"walros-seasonal-background-styles\";\n style.textContent = STYLES;\n document.head.appendChild(style);\n}\n\nfunction getDateParts(date: Date, timeZone: string) {\n const parts = new Intl.DateTimeFormat(\"en-GB\", {\n timeZone,\n day: \"2-digit\",\n month: \"2-digit\",\n year: \"numeric\",\n }).formatToParts(date);\n const value = (type: Intl.DateTimeFormatPartTypes) => Number(parts.find((part) => part.type === type)?.value);\n return { day: value(\"day\"), month: value(\"month\"), year: value(\"year\") };\n}\n\nfunction getUtcOffsetMilliseconds(date: Date, timeZone: string) {\n const parts = new Intl.DateTimeFormat(\"en-GB\", {\n timeZone,\n timeZoneName: \"longOffset\",\n }).formatToParts(date);\n const offset = parts.find((part) => part.type === \"timeZoneName\")?.value ?? \"GMT\";\n const match = offset.match(/^GMT([+-])(\\d{2}):(\\d{2})$/);\n if (!match) return 0;\n const minutes = Number(match[2]) * 60 + Number(match[3]);\n return (match[1] === \"+\" ? 1 : -1) * minutes * 60_000;\n}\n\nfunction millisecondsUntilNextMidnight(timeZone: string) {\n const now = new Date();\n const { year, month, day } = getDateParts(now, timeZone);\n const localNextMidnight = Date.UTC(year, month - 1, day + 1, 0, 0, 1);\n let nextMidnight = localNextMidnight - getUtcOffsetMilliseconds(new Date(localNextMidnight), timeZone);\n nextMidnight = localNextMidnight - getUtcOffsetMilliseconds(new Date(nextMidnight), timeZone);\n return Math.max(1_000, nextMidnight - now.getTime());\n}\n\n/**\n * Returns the campaign active on a date in the selected time zone.\n * Each interval includes its start at 00:00 and excludes its stated end at 00:00.\n */\nexport function getWalrosSeason(date = new Date(), timeZone = \"Europe/Madrid\"): ActiveSeason | null {\n const { day, month } = getDateParts(date, timeZone);\n // 30 Sep 00:00 <= date < 1 Nov 00:00\n if ((month === 9 && day >= 30) || month === 10) return \"halloween\";\n // 30 Nov 00:00 <= date < 11 Jan 00:00\n if ((month === 11 && day >= 30) || month === 12 || (month === 1 && day <= 10)) return \"winter\";\n // 14 Feb 00:00 <= date < 15 Feb 00:00\n if (month === 2 && day === 14) return \"valentine\";\n return null;\n}\n\nfunction useAutomaticSeason(timeZone: string) {\n const [now, setNow] = useState(() => new Date());\n useEffect(() => {\n let timer = 0;\n const refreshAtNextMidnight = () => {\n timer = window.setTimeout(() => {\n setNow(new Date());\n refreshAtNextMidnight();\n }, millisecondsUntilNextMidnight(timeZone));\n };\n refreshAtNextMidnight();\n return () => window.clearTimeout(timer);\n }, [timeZone]);\n\n return getWalrosSeason(now, timeZone);\n}\n\nfunction SnowIcon() {\n return <svg viewBox=\"0 0 32 32\" fill=\"none\" aria-hidden=\"true\"><g stroke=\"currentColor\" strokeWidth=\"2.2\" strokeLinecap=\"round\" strokeLinejoin=\"round\"><path d=\"M16 3v26M4.7 9.5l22.6 13M4.7 22.5l22.6-13\"/><path d=\"m16 3-3 4M16 3l3 4M16 29l-3-4M16 29l3-4M4.7 9.5l4.9.5M4.7 9.5l2 4.5M27.3 22.5l-4.9-.5M27.3 22.5l-2-4.5M4.7 22.5l4.9-.5M4.7 22.5l2-4.5M27.3 9.5l-4.9.5M27.3 9.5l-2 4.5\"/></g></svg>;\n}\n\nfunction PumpkinIcon() {\n return <svg viewBox=\"0 0 160 160\" fill=\"none\" aria-hidden=\"true\"><defs><linearGradient id=\"walros-seasonal-pumpkin\" x1=\"28\" y1=\"44\" x2=\"133\" y2=\"132\" gradientUnits=\"userSpaceOnUse\"><stop stopColor=\"#FF9F17\"/><stop offset=\"1\" stopColor=\"#F06408\"/></linearGradient><linearGradient id=\"walros-seasonal-stem\" x1=\"83\" y1=\"15\" x2=\"105\" y2=\"55\" gradientUnits=\"userSpaceOnUse\"><stop stopColor=\"#45933D\"/><stop offset=\"1\" stopColor=\"#1D642C\"/></linearGradient></defs><path d=\"M88 45c-2-14 3-26 14-34 11 7 17 17 16 31-1 8-5 13-12 15-8 3-15-2-18-12Z\" fill=\"url(#walros-seasonal-stem)\"/><path d=\"M80 36c-36 0-61 22-61 57 0 34 24 53 61 53s61-19 61-53c0-35-25-57-61-57Z\" fill=\"url(#walros-seasonal-pumpkin)\"/><path d=\"M80 38c-18 14-23 75 0 106M51 44c-17 22-17 64 0 94M109 44c17 22 17 64 0 94\" stroke=\"#FFBE3C\" strokeWidth=\"5\" strokeLinecap=\"round\" opacity=\".6\"/><path d=\"m47 82 16-20c2-3 6-3 8 1l8 24c1 4-3 7-7 6l-22-4c-4-1-5-4-3-7ZM113 82 97 62c-2-3-6-3-8 1l-8 24c-1 4 3 7 7 6l22-4c4-1 5-4 3-7ZM78 91l-10 12c-3 3-1 8 4 8h17c5 0 7-5 4-8L83 91c-1-2-4-2-5 0Z\" fill=\"#3A260F\"/><path d=\"M45 112c-2-5 4-8 8-5l10 7 10-7c2-2 5-2 7 0l10 7 10-7c4-3 10 0 8 5l-9 28c-1 4-5 5-8 3l-11-8-11 8c-3 2-7 1-8-3l-16-28Z\" fill=\"#3A260F\"/></svg>;\n}\n\nfunction HeartArrowIcon() {\n return <svg viewBox=\"0 0 160 160\" fill=\"none\" aria-hidden=\"true\"><defs><linearGradient id=\"walros-seasonal-heart\" x1=\"40\" y1=\"51\" x2=\"123\" y2=\"129\" gradientUnits=\"userSpaceOnUse\"><stop stopColor=\"#FF5457\"/><stop offset=\"1\" stopColor=\"#D41E32\"/></linearGradient><linearGradient id=\"walros-seasonal-gold\" x1=\"24\" y1=\"24\" x2=\"135\" y2=\"133\" gradientUnits=\"userSpaceOnUse\"><stop stopColor=\"#FFE958\"/><stop offset=\"1\" stopColor=\"#F3AE19\"/></linearGradient></defs><path d=\"M80 137S28 107 28 64c0-20 14-34 33-34 10 0 16 5 19 12 3-7 9-12 19-12 19 0 33 14 33 34 0 43-52 73-52 73Z\" fill=\"url(#walros-seasonal-heart)\" stroke=\"#C92735\" strokeWidth=\"7\" strokeLinejoin=\"round\"/><path d=\"M76 44c-13-9-28-2-33 12\" stroke=\"#FF9A90\" strokeWidth=\"6\" strokeLinecap=\"round\" opacity=\".45\"/><path d=\"m18 43 37-16-16 37-21-21ZM142 117l-37 16 16-37 21 21Z\" fill=\"url(#walros-seasonal-gold)\" stroke=\"#D8A91C\" strokeWidth=\"5\" strokeLinejoin=\"round\"/><path d=\"m31 53 96 72\" stroke=\"#F5B415\" strokeWidth=\"13\" strokeLinecap=\"round\"/><path d=\"M72 89c0-16 11-24 24-22\" stroke=\"#AE1830\" strokeWidth=\"9\" strokeLinecap=\"round\"/></svg>;\n}\n\nfunction Decoration({ season }: { season: ActiveSeason }) {\n if (season === \"halloween\") return <PumpkinIcon />;\n if (season === \"winter\") return <SnowIcon />;\n return <HeartArrowIcon />;\n}\n\nfunction getSeasonColor(season: ActiveSeason) {\n if (season === \"halloween\") return \"transparent\";\n if (season === \"winter\") return \"#78B7E8\";\n return \"transparent\";\n}\n\nexport function WalrosSeasonalBackground({\n children,\n season = \"auto\",\n timeZone = \"Europe/Madrid\",\n density = 20,\n enabled = true,\n className,\n contentClassName,\n style,\n}: WalrosSeasonalBackgroundProps) {\n useEffect(() => installStyles(), []);\n\n const automaticSeason = useAutomaticSeason(timeZone);\n const activeSeason = season === \"auto\" ? automaticSeason : season === \"none\" ? null : season;\n const particleCount = Math.max(1, Math.min(PARTICLES.length, Math.round(density)));\n const particles = useMemo(() => PARTICLES.slice(0, particleCount), [particleCount]);\n\n return (\n <div className={classNames(\"walros-seasonal-background\", className)} style={style}>\n {enabled && activeSeason && (\n <div className=\"walros-seasonal-background__decorations\" aria-hidden=\"true\">\n {particles.map(([, top, , duration, sway], index) => {\n // Each decoration starts at a different point in its trip, so the\n // page stays evenly populated instead of collecting at one edge.\n const elapsed = (index / particleCount) * duration;\n return <span\n className=\"walros-seasonal-background__particle\"\n key={`${activeSeason}-${index}`}\n style={{\n \"--walros-seasonal-top\": `${top}%`,\n \"--walros-seasonal-delay\": `-${elapsed}s`,\n \"--walros-seasonal-duration\": `${duration}s`,\n \"--walros-seasonal-sway\": `${sway}px`,\n \"--walros-seasonal-opacity\": \".52\",\n \"--walros-seasonal-color\": getSeasonColor(activeSeason),\n } as CSSProperties}\n >\n <Decoration season={activeSeason} />\n </span>;\n })}\n </div>\n )}\n <div className={classNames(\"walros-seasonal-background__content\", contentClassName)}>{children}</div>\n </div>\n );\n}\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?.remove();\n soundRef.current = new Audio(soundUrlRef.current);\n soundRef.current.preload = \"auto\";\n soundRef.current.setAttribute(\"aria-hidden\", \"true\");\n soundRef.current.style.display = \"none\";\n document.body.appendChild(soundRef.current);\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 soundRef.current?.remove();\n if (soundRef.current) soundRef.current.currentTime = 0;\n soundRef.current = null;\n };\n }, [clearTimers, removeShakeClasses, unlockViewport]);\n\n return {\n theme,\n isDark: theme === \"dark\",\n mounted,\n glitching,\n toggleTheme,\n setTheme,\n };\n}\n\nexport default useWalrosTheme;\n"],"mappings":";AAAA,SAAS,YAAAA,iBAAgB;AACzB,SAAS,oBAAoB;;;ACD7B,SAAS,OAAO,iBAAiB,QAAQ,gBAAgB;AACzD,OAAO,UAAU;;;ACAV,IAAM,oBAAoB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AACF;;;AD8EY,SACJ,KADI;AApEZ,IAAM,qBAAqB;AAC3B,IAAM,UAAU;AAChB,IAAM,UAAU;AAChB,IAAM,gBAAgB;AAGf,SAAS,yBAAyB;AAAA,EACvC;AAAA,EACA,WAAW;AAAA,EACX,kBAAkB;AAAA,EAClB,SAAS;AAAA,EACT,aAAa;AACf,GAAkC;AAChC,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,IAAI;AAC3C,QAAM,CAAC,QAAQ,IAAI,SAAS,OAAO;AAAA,IACjC,OAAO,OAAO,WAAW,cAAc,IAAI,OAAO;AAAA,IAClD,QAAQ,OAAO,WAAW,cAAc,IAAI,OAAO;AAAA,EACrD,EAAE;AACF,QAAM,UAAU,OAAuB,IAAI;AAC3C,QAAM,YAAY,OAAoB,IAAI;AAC1C,QAAM,cAAc,OAAO,UAAU;AACrC,cAAY,UAAU;AACtB,QAAM,SAAS,sBAAsB,MAAM,EAAE,QAAQ,MAAM,GAAG,CAAC;AAE/D,kBAAgB,MAAM;AACpB,QAAI,CAAC,WAAW,SAAS,SAAS,KAAK,SAAS,UAAU,KAAK,CAAC,QAAQ,WAAW,CAAC,UAAU,QAAS;AACvG,UAAM,mBAAmB,SAAS,KAAK,MAAM;AAC7C,QAAI,WAAY,UAAS,KAAK,MAAM,WAAW;AAE/C,UAAMC,iBAAgB,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,SAAS,QAAQ,IAAI,CAAC;AACxE,UAAMC,gBAAeD,iBAAgB;AACrC,UAAM,cAAc,KAAK,MAAM,SAAS,OAAO,SAAS,MAAM,IAAI,IAAI,MAAM,gBAAgB;AAC5F,UAAME,gBAAe,qBAAqB;AAC1C,UAAMC,iBAAgB,SAAS,QAAQ,KAAKD,gBAAe,WAAWD;AACtE,UAAMG,iBAAgB,SAAS,SAAS,KAAKF,gBAAe,WAAWD;AACvE,UAAM,QAAQ,WAAW;AAEzB,SAAK,IAAI,UAAU,SAAS,EAAE,OAAOA,eAAc,WAAW,MAAM,CAAC;AACrE,SAAK,IAAI,QAAQ,SAAS,EAAE,SAAS,EAAE,CAAC;AACxC,UAAM,SAAS,MAAM;AACnB,UAAI,WAAY,UAAS,KAAK,MAAM,WAAW;AAC/C,iBAAW,KAAK;AAChB,kBAAY,UAAU;AAAA,IACxB;AACA,UAAM,WAAW,KAAK,SAAS,EAAE,YAAY,OAAO,CAAC;AACrD,QAAI,OAAO,WAAW,kCAAkC,EAAE,SAAS;AACjE,eAAS,GAAG,QAAQ,SAAS,EAAE,SAAS,GAAG,UAAU,MAAM,MAAM,aAAa,CAAC;AAAA,IACjF,OAAO;AACL,eACG,GAAG,UAAU,SAAS,EAAE,OAAOA,gBAAe,KAAK,UAAU,QAAQ,MAAM,MAAM,aAAa,GAAG,CAAC,EAClG,GAAG,UAAU,SAAS,EAAE,OAAO,YAAY,UAAU,QAAQ,MAAM,MAAM,YAAY,GAAG,QAAQ,IAAI,EACpG,GAAG,QAAQ,SAAS,EAAE,SAAS,GAAG,UAAU,QAAQ,KAAK,MAAM,aAAa,GAAG,QAAQ,GAAG;AAAA,IAC/F;AACA,WAAO,MAAM;AACX,eAAS,KAAK;AACd,UAAI,WAAY,UAAS,KAAK,MAAM,WAAW;AAAA,IACjD;AAAA,EACF,GAAG,CAAC,UAAU,YAAY,UAAU,OAAO,CAAC;AAE5C,MAAI,CAAC,QAAS,QAAO;AACrB,QAAM,gBAAgB,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,SAAS,QAAQ,IAAI,CAAC;AACxE,QAAM,eAAe,gBAAgB;AACrC,QAAM,eAAe,qBAAqB;AAC1C,QAAM,gBAAgB,SAAS,QAAQ,KAAK,eAAe,WAAW;AACtE,QAAM,gBAAgB,SAAS,SAAS,KAAK,eAAe,WAAW;AAEvE,SAAO,oBAAC,SAAI,KAAK,SAAS,WAAU,oBAAmB,eAAY,QAAO,OAAO,EAAE,UAAU,SAAS,OAAO,GAAG,OAAO,SAAS,QAAQ,UAAU,UAAU,UAAU,eAAe,QAAQ,QAAQ,iBAAiB,SAAS,QAAQ,IAAI,gBAAgB,gBAAgB,GACzQ,+BAAC,SAAI,OAAM,QAAO,QAAO,QAAO,SAAS,OAAO,SAAS,KAAK,IAAI,SAAS,MAAM,IAAI,qBAAoB,QAAO,OAAO,EAAE,SAAS,QAAO,GACvI;AAAA,wBAAC,UAAK,+BAAC,UAAK,IAAI,QAAQ,WAAU,kBAAiB,GAAE,KAAI,GAAE,KAAI,OAAO,SAAS,OAAO,QAAQ,SAAS,QACrG;AAAA,0BAAC,UAAK,OAAO,SAAS,OAAO,QAAQ,SAAS,QAAQ,MAAK,SAAQ;AAAA,MACnE,oBAAC,OAAE,WAAW,aAAa,aAAa,IAAI,aAAa,KACvD,8BAAC,OAAE,KAAK,WAAW,WAAW,SAAS,YAAY,KACjD,8BAAC,OAAE,WAAW,aAAa,CAAC,OAAO,IAAI,CAAC,OAAO,KAAK,MAAK,SACtD,4BAAkB,IAAI,CAAC,MAAM,UAAU,oBAAC,UAAK,GAAG,QAAW,KAAO,CAAE,GACvE,GACF,GACF;AAAA,OACF,GAAO;AAAA,IACP,oBAAC,UAAK,OAAO,SAAS,OAAO,QAAQ,SAAS,QAAQ,MAAM,iBAAiB,MAAM,QAAQ,MAAM,KAAK;AAAA,KACxG,GACF;AACF;;;AEhGA,SAAS,mBAAAI,kBAAiB,YAAAC,iBAAgB;AAInC,SAAS,eAAe,QAAgB;AAC7C,QAAM,CAAC,IAAI,IAAIA;AAAA,IAAgC,MAC7C,OAAO,aAAa,cAAc,OAAO,SAAS,cAAc,KAAK;AAAA,EACvE;AAEA,EAAAD,iBAAgB,MAAM;AACpB,QAAI,CAAC,KAAM;AACX,SAAK,QAAQ,oBAAoB;AACjC,SAAK,MAAM,WAAW;AACtB,SAAK,MAAM,QAAQ;AACnB,SAAK,MAAM,gBAAgB;AAC3B,aAAS,gBAAgB,YAAY,IAAI;AACzC,WAAO,MAAM,KAAK,OAAO;AAAA,EAC3B,GAAG,CAAC,IAAI,CAAC;AAET,EAAAA,iBAAgB,MAAM;AACpB,QAAI,KAAM,MAAK,MAAM,SAAS,OAAO,MAAM;AAAA,EAC7C,GAAG,CAAC,MAAM,MAAM,CAAC;AAEjB,SAAO;AACT;;;AHyCI,gBAAAE,YAAA;AAhDJ,SAAS,gBAA8B;AACrC,MAAI,OAAO,WAAW,YAAa,QAAO,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,IAAI,QAAQ,GAAG;AAC1F,SAAO;AAAA,IACL,SAAS,OAAO,aAAa;AAAA,IAC7B,SAAS,OAAO,cAAc;AAAA,IAC9B,OAAO;AAAA,IACP,QAAQ;AAAA,EACV;AACF;AAEA,SAAS,WAAW,MAA0C;AAC5D,MAAI,OAAO,WAAW,YAAa,QAAO;AAC1C,MAAI;AACF,WAAO,SAAS,YAAY,OAAO,iBAAiB,OAAO;AAAA,EAC7D,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,UAAU,SAAkB,MAAqC,KAAa;AACrF,MAAI,CAAC,QAAS,QAAO;AACrB,MAAI,SAAS,SAAU,QAAO;AAC9B,MAAI;AACF,WAAO,WAAW,IAAI,GAAG,QAAQ,GAAG,KAAK;AAAA,EAC3C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGO,SAAS,uBAAuB;AAAA,EACrC,WAAW;AAAA,EACX;AAAA,EACA,kBAAkB;AAAA,EAClB,UAAU;AAAA,EACV,cAAc;AAAA,EACd,aAAa;AAAA,EACb,SAAS;AAAA,EACT;AACF,GAAgC;AAC9B,QAAM,CAAC,GAAG,IAAIC,UAAS,MAAM,UAAU,SAAS,aAAa,UAAU,CAAC;AACxE,QAAM,CAAC,UAAU,WAAW,IAAIA,UAAS,KAAK;AAC9C,QAAM,CAAC,aAAa,IAAIA,UAAS,MAAM,UAAU,cAAc,CAAC;AAChE,QAAM,OAAO,eAAe,MAAM;AAElC,MAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,OAAO,SAAU,QAAO;AAElD,SAAO;AAAA,IACL,gBAAAD;AAAA,MAAC;AAAA;AAAA,QACC,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,QACA,QAAQ;AAAA,QACR,YAAU;AAAA,QACV,YAAY,MAAM;AAChB,cAAI,gBAAgB,UAAU;AAC5B,gBAAI;AAAE,yBAAW,WAAW,GAAG,QAAQ,YAAY,GAAG;AAAA,YAAG,QAAQ;AAAA,YAA6B;AAAA,UAChG;AACA,sBAAY,IAAI;AAChB,uBAAa;AAAA,QACf;AAAA;AAAA,IACF;AAAA,IACA;AAAA,EACF;AACF;;;AIjFA,SAAS,gBAAAE,qBAAoB;;;AC4JzB,mBACE,OAAAC,MAEE,QAAAC,aAHJ;AAnJJ,IAAM,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA4If,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA,SAAS;AAAA,EACT;AAAA,EACA;AACF,GAA2B;AACzB,SACE,gBAAAA,MAAA,YACE;AAAA,oBAAAD,KAAC,WAAO,yBAAc;AAAA,IACrB,SACC,gBAAAC;AAAA,MAAC;AAAA;AAAA,QACC,WAAW,CAAC,4BAA4B,aAAa,SAAS,EAC3D,OAAO,OAAO,EACd,KAAK,GAAG;AAAA,QACX,OAAO,EAAE,QAAQ,GAAG,MAAM;AAAA,QAC1B,eAAY;AAAA,QAEZ;AAAA,0BAAAD,KAAC,UAAK,WAAU,4BAA2B;AAAA,UAC3C,gBAAAA,KAAC,UAAK,WAAU,4BAA2B;AAAA,UAC3C,gBAAAA,KAAC,UAAK,WAAU,4BAA2B;AAAA,UAC3C,gBAAAA,KAAC,UAAK,WAAU,4BAA2B;AAAA;AAAA;AAAA,IAC7C,IACE;AAAA,KACN;AAEJ;;;ADvJI,gBAAAE,YAAA;AARG,SAAS,sBAAsB;AAAA,EACpC;AAAA,EACA,SAAS;AACX,GAA+B;AAC7B,QAAM,OAAO,eAAe,MAAM;AAClC,MAAI,CAAC,KAAM,QAAO;AAElB,SAAOC;AAAA,IACL,gBAAAD,KAAC,qBAAkB,QAAgB,QAAQ,GAAG;AAAA,IAC9C;AAAA,EACF;AACF;;;AE1BA,SAAS,WAAW,UAAAE,eAAc;;;ACC3B,IAAM,mBAAmB;;;ADmK5B,qBAAAC,WAAE,OAAAC,MAGI,QAAAC,aAHN;AAjKJ,IAAM,uBAAuB;AAE7B,IAAM,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAetB,IAAM,sBAAsB;AAC5B,IAAM,uBAAuB;AAEtB,SAAS,oBAAoB;AAClC,QAAM,gBAAgBC,QAAuB,IAAI;AACjD,QAAM,iBAAiBA,QAAuB,IAAI;AAElD,YAAU,MAAM;AACd,UAAM,WAAW,cAAc;AAC/B,UAAM,YAAY,eAAe;AACjC,QAAI,CAAC,YAAY,CAAC,UAAW;AAE7B,UAAM,QAAQ,OAAO,WAAW,oBAAoB;AACpD,QAAI,SAAS;AACb,QAAI,QAAQ;AACZ,QAAI,YAAY;AAChB,QAAI,aAAa;AACjB,QAAI,cAAiC;AACrC,QAAI,WAAW,OAAO,aAAa;AACnC,QAAI,WAAW;AACf,QAAI,UAAU;AACd,QAAI,UAAU;AACd,QAAI,eAAe;AACnB,QAAI,cAAc;AAClB,QAAI,WAAW;AACf,QAAI,eAAe;AACnB,QAAI,cAAc;AAClB,QAAI,QAAQ;AACZ,QAAI,QAAQ;AAEZ,UAAM,mBAAmB,CAAC,gBAAoC;AAC5D,YAAM,SAAS,uBAAuB,UAAU,cAAc;AAC9D,YAAM,YAAY,QAAQ,QAAQ,mBAAmB;AACrD,YAAM,cAAc,QAAQ,QAAQ,oBAAoB;AAKxD,eAAS,UAAU,OAAO,cAAc,CAAC,SAAS;AAClD,eAAS,UAAU,OAAO,WAAW,QAAQ,eAAe,CAAC,SAAS,CAAC;AAAA,IACzE;AAEA,UAAM,SAAS,MAAM;AACnB,mBAAa,UAAU,YAAY;AACnC,mBAAa,UAAU,YAAY;AACnC,YAAM,cAAe,cAAc,eAAe,OAAO,MAAO;AAChE,sBAAgB,aAAa;AAC7B,uBAAiB,cAAc,gBAAgB;AAE/C,eAAS,MAAM,YAAY,eAAe,QAAQ,OAAO,QAAQ;AACjE,gBAAU,MAAM,YAAY,gCAAgC,YAAY,cAAc,YAAY;AAElG,YAAM,YAAY,KAAK,IAAI,UAAU,QAAQ,IAAI,QAC5C,KAAK,IAAI,UAAU,QAAQ,IAAI,QAC/B,KAAK,IAAI,UAAU,IAAI,QACvB,KAAK,IAAI,cAAc,YAAY,IAAI;AAC5C,cAAQ,YAAY,OAAO,sBAAsB,MAAM,IAAI;AAAA,IAC7D;AAEA,UAAM,gBAAgB,MAAM;AAC1B,UAAI,CAAC,MAAO,SAAQ,OAAO,sBAAsB,MAAM;AAAA,IACzD;AAEA,UAAM,cAAc,MAAM;AACxB,kBAAY;AACZ,YAAM,QAAQ;AACd,UAAI,CAAC,MAAO;AACZ,YAAM,SAAS,MAAM,UAAU;AAC/B,YAAM,SAAS,MAAM,UAAU;AAC/B,YAAM,WAAW,KAAK,MAAM,QAAQ,MAAM;AAC1C,gBAAU,MAAM;AAChB,gBAAU,MAAM;AAChB,uBAAiB,MAAM,MAAM;AAE7B,UAAI,WAAW,MAAM;AACnB,cAAM,WAAW,KAAK,MAAM,QAAQ,MAAM,KAAK,MAAM,KAAK,MAAM;AAChE,cAAM,mBAAmB,WAAW,MAAM,OAAO;AACjD,YAAI,CAAC,UAAU;AACb,wBAAc;AACd,yBAAe;AACf,qBAAW;AAAA,QACb,OAAO;AACL,wBAAc;AAAA,QAChB;AAEA,sBAAc;AACd,eAAO,aAAa,UAAU;AAC9B,qBAAa,OAAO,WAAW,MAAM;AACnC,wBAAc;AACd,wBAAc;AAAA,QAChB,GAAG,GAAG;AAAA,MACR;AAEA,cAAQ,MAAM;AACd,cAAQ,MAAM;AACd,oBAAc;AAAA,IAChB;AAEA,UAAM,kBAAkB,CAAC,UAAsB;AAC7C,oBAAc;AACd,UAAI,CAAC,UAAW,aAAY,OAAO,sBAAsB,WAAW;AAAA,IACtE;AAEA,UAAM,kBAAkB,CAAC,UAAsB;AAC7C,uBAAiB,MAAM,MAAM;AAAA,IAC/B;AAEA,UAAM,WAAW,MAAM;AACrB,UAAI,OAAQ;AACZ,eAAS;AACT,eAAS,gBAAgB,UAAU,IAAI,wBAAwB;AAC/D,aAAO,iBAAiB,aAAa,iBAAiB,EAAE,SAAS,KAAK,CAAC;AACvE,aAAO,iBAAiB,aAAa,iBAAiB,EAAE,SAAS,KAAK,CAAC;AAAA,IACzE;AAEA,UAAM,aAAa,MAAM;AACvB,UAAI,CAAC,OAAQ;AACb,eAAS;AACT,eAAS,gBAAgB,UAAU,OAAO,wBAAwB;AAClE,eAAS,UAAU,OAAO,YAAY;AACtC,eAAS,UAAU,OAAO,SAAS;AACnC,aAAO,oBAAoB,aAAa,eAAe;AACvD,aAAO,oBAAoB,aAAa,eAAe;AACvD,aAAO,qBAAqB,KAAK;AACjC,aAAO,qBAAqB,SAAS;AACrC,aAAO,aAAa,UAAU;AAC9B,cAAQ;AACR,kBAAY;AAAA,IACd;AAEA,UAAM,OAAO,MAAM;AACjB,UAAI,MAAM,QAAS,UAAS;AAAA,UACvB,YAAW;AAAA,IAClB;AACA,UAAM,iBAAiB,UAAU,IAAI;AACrC,SAAK;AAEL,WAAO,MAAM;AACX,YAAM,oBAAoB,UAAU,IAAI;AACxC,iBAAW;AAAA,IACb;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,SACE,gBAAAD,MAAAF,WAAA,EAAE;AAAA,oBAAAC,KAAC,WAAO,yBAAc;AAAA,IAAQ,gBAAAC,MAAC,SAAI,KAAK,eAAe,WAAU,sBAAqB,eAAY,QAClG;AAAA,sBAAAD,KAAC,SAAI,KAAK,gBAAgB,WAAU,4BAClC,0BAAAC,MAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QAAO,OAAM,8BAChE;AAAA,wBAAAA,MAAC,OAAE,QAAO,8BACR;AAAA,0BAAAD,KAAC,UAAK,GAAE,qRAAoR,MAAK,SAAQ;AAAA,UACzS,gBAAAA,KAAC,UAAK,GAAE,gRAA+Q,QAAO,SAAQ,aAAY,WAAU;AAAA,WAC9T;AAAA,QACA,gBAAAA,KAAC,UACC,0BAAAC,MAAC,YAAO,IAAG,wBAAuB,GAAE,YAAW,GAAE,YAAW,OAAM,WAAU,QAAO,UAAS,aAAY,kBAAiB,2BAA0B,QACjJ;AAAA,0BAAAD,KAAC,aAAQ,cAAa,KAAI,QAAO,sBAAqB;AAAA,UACtD,gBAAAA,KAAC,mBAAc,IAAG,eAAc,MAAK,UAAS,QAAO,6CAA4C,QAAO,aAAY;AAAA,UACpH,gBAAAA,KAAC,cAAS,IAAG,WAAU;AAAA,UACvB,gBAAAA,KAAC,oBAAe,cAAa,WAAU;AAAA,UACvC,gBAAAA,KAAC,iBAAY,KAAI,aAAY,UAAS,OAAM;AAAA,UAC5C,gBAAAA,KAAC,mBAAc,MAAK,UAAS,QAAO,8CAA6C;AAAA,UACjF,gBAAAA,KAAC,aAAQ,MAAK,UAAS,KAAI,sBAAqB,QAAO,sBAAqB;AAAA,UAC5E,gBAAAA,KAAC,aAAQ,MAAK,UAAS,IAAG,iBAAgB,KAAI,sBAAqB,QAAO,SAAQ;AAAA,WACpF,GACF;AAAA,SACF,GACF;AAAA,MACA,gBAAAA,KAAC,SAAI,WAAU,2BAA0B,KAAK,kBAAkB,KAAI,IAAG;AAAA,OACzE;AAAA,KAAM;AAEV;;;AE5LO,IAAM,4BAA4B,IAAI;AAAA,EAC3C;AAAA,EACA,YAAY;AACd,EAAE;AAEK,IAAM,sBAAsB,IAAI;AAAA,EACrC;AAAA,EACA,YAAY;AACd,EAAE;AAEK,IAAM,yBAAyB,IAAI;AAAA,EACxC;AAAA,EACA,YAAY;AACd,EAAE;AAEK,IAAM,wBAAwB,IAAI;AAAA,EACvC;AAAA,EACA,YAAY;AACd,EAAE;AAEK,IAAM,4BAA4B,IAAI;AAAA,EAC3C;AAAA,EACA,YAAY;AACd,EAAE;AAEK,IAAM,2BAA2B,IAAI;AAAA,EAC1C;AAAA,EACA,YAAY;AACd,EAAE;AAEK,IAAM,8BAA8B,IAAI;AAAA,EAC7C;AAAA,EACA,YAAY;AACd,EAAE;;;ACnBE,gBAAAG,YAAA;AANG,SAAS,WAAW;AAAA,EACzB,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,GAAG;AACL,GAAoB;AAClB,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;;;ACII,gBAAAC,YAAA;AAZG,SAAS,eAAe;AAAA,EAC7B,UAAU;AAAA,EACV,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,GAAG;AACL,GAAwB;AACtB,QAAM,MACJ,YAAY,SACR,wBACA;AAEN,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;;;AChCA,SAAS,aAAAC,YAAW,SAAS,YAAAC,iBAAgB;AAsKoB,SAAwF,OAAAC,MAAxF,QAAAC,aAAA;AAjJjE,IAAM,YAAY;AAAA,EAChB,CAAC,GAAG,GAAG,GAAG,IAAI,KAAK,IAAI;AAAA,EAAG,CAAC,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI;AAAA,EACpD,CAAC,IAAI,IAAI,KAAK,IAAI,KAAK,GAAG;AAAA,EAAG,CAAC,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI;AAAA,EACvD,CAAC,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI;AAAA,EAAG,CAAC,IAAI,IAAI,MAAM,IAAI,IAAI,IAAI;AAAA,EACzD,CAAC,IAAI,GAAG,MAAM,IAAI,KAAK,IAAI;AAAA,EAAG,CAAC,IAAI,IAAI,MAAM,IAAI,IAAI,GAAG;AAAA,EACxD,CAAC,IAAI,IAAI,MAAM,IAAI,KAAK,IAAI;AAAA,EAAG,CAAC,IAAI,IAAI,MAAM,IAAI,IAAI,IAAI;AAAA,EAC1D,CAAC,IAAI,IAAI,MAAM,IAAI,KAAK,GAAG;AAAA,EAAG,CAAC,IAAI,IAAI,MAAM,IAAI,IAAI,GAAG;AAAA,EACxD,CAAC,IAAI,IAAI,MAAM,IAAI,KAAK,IAAI;AAAA,EAAG,CAAC,IAAI,IAAI,MAAM,IAAI,IAAI,IAAI;AAAA,EAC1D,CAAC,IAAI,IAAI,MAAM,IAAI,KAAK,GAAG;AAAA,EAAG,CAAC,IAAI,IAAI,MAAM,IAAI,IAAI,GAAG;AAAA,EACxD,CAAC,GAAG,IAAI,KAAK,IAAI,KAAK,GAAG;AAAA,EAAG,CAAC,IAAI,IAAI,KAAK,IAAI,IAAI,GAAG;AAAA,EACrD,CAAC,IAAI,IAAI,MAAM,IAAI,KAAK,GAAG;AAAA,EAAG,CAAC,IAAI,IAAI,MAAM,IAAI,IAAI,GAAG;AAAA,EACxD,CAAC,IAAI,IAAI,MAAM,IAAI,KAAK,GAAG;AAAA,EAAG,CAAC,IAAI,GAAG,MAAM,IAAI,IAAI,GAAG;AAAA,EACvD,CAAC,IAAI,IAAI,MAAM,IAAI,KAAK,GAAG;AAAA,EAAG,CAAC,IAAI,IAAI,MAAM,IAAI,IAAI,GAAG;AAC1D;AAEA,IAAM,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAqDf,SAAS,cAAc,QAAmC;AACxD,SAAO,OAAO,OAAO,OAAO,EAAE,KAAK,GAAG;AACxC;AAEA,SAAS,gBAAgB;AACvB,MAAI,OAAO,aAAa,eAAe,SAAS,eAAe,mCAAmC,EAAG;AACrG,QAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,QAAM,KAAK;AACX,QAAM,cAAc;AACpB,WAAS,KAAK,YAAY,KAAK;AACjC;AAEA,SAAS,aAAa,MAAY,UAAkB;AAClD,QAAM,QAAQ,IAAI,KAAK,eAAe,SAAS;AAAA,IAC7C;AAAA,IACA,KAAK;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,EACR,CAAC,EAAE,cAAc,IAAI;AACrB,QAAM,QAAQ,CAAC,SAAuC,OAAO,MAAM,KAAK,CAAC,SAAS,KAAK,SAAS,IAAI,GAAG,KAAK;AAC5G,SAAO,EAAE,KAAK,MAAM,KAAK,GAAG,OAAO,MAAM,OAAO,GAAG,MAAM,MAAM,MAAM,EAAE;AACzE;AAEA,SAAS,yBAAyB,MAAY,UAAkB;AAC9D,QAAM,QAAQ,IAAI,KAAK,eAAe,SAAS;AAAA,IAC7C;AAAA,IACA,cAAc;AAAA,EAChB,CAAC,EAAE,cAAc,IAAI;AACrB,QAAM,SAAS,MAAM,KAAK,CAAC,SAAS,KAAK,SAAS,cAAc,GAAG,SAAS;AAC5E,QAAM,QAAQ,OAAO,MAAM,4BAA4B;AACvD,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,UAAU,OAAO,MAAM,CAAC,CAAC,IAAI,KAAK,OAAO,MAAM,CAAC,CAAC;AACvD,UAAQ,MAAM,CAAC,MAAM,MAAM,IAAI,MAAM,UAAU;AACjD;AAEA,SAAS,8BAA8B,UAAkB;AACvD,QAAM,MAAM,oBAAI,KAAK;AACrB,QAAM,EAAE,MAAM,OAAO,IAAI,IAAI,aAAa,KAAK,QAAQ;AACvD,QAAM,oBAAoB,KAAK,IAAI,MAAM,QAAQ,GAAG,MAAM,GAAG,GAAG,GAAG,CAAC;AACpE,MAAI,eAAe,oBAAoB,yBAAyB,IAAI,KAAK,iBAAiB,GAAG,QAAQ;AACrG,iBAAe,oBAAoB,yBAAyB,IAAI,KAAK,YAAY,GAAG,QAAQ;AAC5F,SAAO,KAAK,IAAI,KAAO,eAAe,IAAI,QAAQ,CAAC;AACrD;AAMO,SAAS,gBAAgB,OAAO,oBAAI,KAAK,GAAG,WAAW,iBAAsC;AAClG,QAAM,EAAE,KAAK,MAAM,IAAI,aAAa,MAAM,QAAQ;AAElD,MAAK,UAAU,KAAK,OAAO,MAAO,UAAU,GAAI,QAAO;AAEvD,MAAK,UAAU,MAAM,OAAO,MAAO,UAAU,MAAO,UAAU,KAAK,OAAO,GAAK,QAAO;AAEtF,MAAI,UAAU,KAAK,QAAQ,GAAI,QAAO;AACtC,SAAO;AACT;AAEA,SAAS,mBAAmB,UAAkB;AAC5C,QAAM,CAAC,KAAK,MAAM,IAAIF,UAAS,MAAM,oBAAI,KAAK,CAAC;AAC/C,EAAAD,WAAU,MAAM;AACd,QAAI,QAAQ;AACZ,UAAM,wBAAwB,MAAM;AAClC,cAAQ,OAAO,WAAW,MAAM;AAC9B,eAAO,oBAAI,KAAK,CAAC;AACjB,8BAAsB;AAAA,MACxB,GAAG,8BAA8B,QAAQ,CAAC;AAAA,IAC5C;AACA,0BAAsB;AACtB,WAAO,MAAM,OAAO,aAAa,KAAK;AAAA,EACxC,GAAG,CAAC,QAAQ,CAAC;AAEb,SAAO,gBAAgB,KAAK,QAAQ;AACtC;AAEA,SAAS,WAAW;AAClB,SAAO,gBAAAE,KAAC,SAAI,SAAQ,aAAY,MAAK,QAAO,eAAY,QAAO,0BAAAC,MAAC,OAAE,QAAO,gBAAe,aAAY,OAAM,eAAc,SAAQ,gBAAe,SAAQ;AAAA,oBAAAD,KAAC,UAAK,GAAE,6CAA2C;AAAA,IAAE,gBAAAA,KAAC,UAAK,GAAE,yKAAuK;AAAA,KAAE,GAAI;AACnY;AAEA,SAAS,cAAc;AACrB,SAAO,gBAAAC,MAAC,SAAI,SAAQ,eAAc,MAAK,QAAO,eAAY,QAAO;AAAA,oBAAAA,MAAC,UAAK;AAAA,sBAAAA,MAAC,oBAAe,IAAG,2BAA0B,IAAG,MAAK,IAAG,MAAK,IAAG,OAAM,IAAG,OAAM,eAAc,kBAAiB;AAAA,wBAAAD,KAAC,UAAK,WAAU,WAAS;AAAA,QAAE,gBAAAA,KAAC,UAAK,QAAO,KAAI,WAAU,WAAS;AAAA,SAAE;AAAA,MAAiB,gBAAAC,MAAC,oBAAe,IAAG,wBAAuB,IAAG,MAAK,IAAG,MAAK,IAAG,OAAM,IAAG,MAAK,eAAc,kBAAiB;AAAA,wBAAAD,KAAC,UAAK,WAAU,WAAS;AAAA,QAAE,gBAAAA,KAAC,UAAK,QAAO,KAAI,WAAU,WAAS;AAAA,SAAE;AAAA,OAAiB;AAAA,IAAO,gBAAAA,KAAC,UAAK,GAAE,2EAA0E,MAAK,8BAA4B;AAAA,IAAE,gBAAAA,KAAC,UAAK,GAAE,2EAA0E,MAAK,iCAA+B;AAAA,IAAE,gBAAAA,KAAC,UAAK,GAAE,6EAA4E,QAAO,WAAU,aAAY,KAAI,eAAc,SAAQ,SAAQ,MAAI;AAAA,IAAE,gBAAAA,KAAC,UAAK,GAAE,6LAA4L,MAAK,WAAS;AAAA,IAAE,gBAAAA,KAAC,UAAK,GAAE,wHAAuH,MAAK,WAAS;AAAA,KAAE;AACrrC;AAEA,SAAS,iBAAiB;AACxB,SAAO,gBAAAC,MAAC,SAAI,SAAQ,eAAc,MAAK,QAAO,eAAY,QAAO;AAAA,oBAAAA,MAAC,UAAK;AAAA,sBAAAA,MAAC,oBAAe,IAAG,yBAAwB,IAAG,MAAK,IAAG,MAAK,IAAG,OAAM,IAAG,OAAM,eAAc,kBAAiB;AAAA,wBAAAD,KAAC,UAAK,WAAU,WAAS;AAAA,QAAE,gBAAAA,KAAC,UAAK,QAAO,KAAI,WAAU,WAAS;AAAA,SAAE;AAAA,MAAiB,gBAAAC,MAAC,oBAAe,IAAG,wBAAuB,IAAG,MAAK,IAAG,MAAK,IAAG,OAAM,IAAG,OAAM,eAAc,kBAAiB;AAAA,wBAAAD,KAAC,UAAK,WAAU,WAAS;AAAA,QAAE,gBAAAA,KAAC,UAAK,QAAO,KAAI,WAAU,WAAS;AAAA,SAAE;AAAA,OAAiB;AAAA,IAAO,gBAAAA,KAAC,UAAK,GAAE,2GAA0G,MAAK,+BAA8B,QAAO,WAAU,aAAY,KAAI,gBAAe,SAAO;AAAA,IAAE,gBAAAA,KAAC,UAAK,GAAE,2BAA0B,QAAO,WAAU,aAAY,KAAI,eAAc,SAAQ,SAAQ,OAAK;AAAA,IAAE,gBAAAA,KAAC,UAAK,GAAE,yDAAwD,MAAK,8BAA6B,QAAO,WAAU,aAAY,KAAI,gBAAe,SAAO;AAAA,IAAE,gBAAAA,KAAC,UAAK,GAAE,gBAAe,QAAO,WAAU,aAAY,MAAK,eAAc,SAAO;AAAA,IAAE,gBAAAA,KAAC,UAAK,GAAE,2BAA0B,QAAO,WAAU,aAAY,KAAI,eAAc,SAAO;AAAA,KAAE;AACtkC;AAEA,SAAS,WAAW,EAAE,OAAO,GAA6B;AACxD,MAAI,WAAW,YAAa,QAAO,gBAAAA,KAAC,eAAY;AAChD,MAAI,WAAW,SAAU,QAAO,gBAAAA,KAAC,YAAS;AAC1C,SAAO,gBAAAA,KAAC,kBAAe;AACzB;AAEA,SAAS,eAAe,QAAsB;AAC5C,MAAI,WAAW,YAAa,QAAO;AACnC,MAAI,WAAW,SAAU,QAAO;AAChC,SAAO;AACT;AAEO,SAAS,yBAAyB;AAAA,EACvC;AAAA,EACA,SAAS;AAAA,EACT,WAAW;AAAA,EACX,UAAU;AAAA,EACV,UAAU;AAAA,EACV;AAAA,EACA;AAAA,EACA;AACF,GAAkC;AAChC,EAAAF,WAAU,MAAM,cAAc,GAAG,CAAC,CAAC;AAEnC,QAAM,kBAAkB,mBAAmB,QAAQ;AACnD,QAAM,eAAe,WAAW,SAAS,kBAAkB,WAAW,SAAS,OAAO;AACtF,QAAM,gBAAgB,KAAK,IAAI,GAAG,KAAK,IAAI,UAAU,QAAQ,KAAK,MAAM,OAAO,CAAC,CAAC;AACjF,QAAM,YAAY,QAAQ,MAAM,UAAU,MAAM,GAAG,aAAa,GAAG,CAAC,aAAa,CAAC;AAElF,SACE,gBAAAG,MAAC,SAAI,WAAW,WAAW,8BAA8B,SAAS,GAAG,OAClE;AAAA,eAAW,gBACV,gBAAAD,KAAC,SAAI,WAAU,2CAA0C,eAAY,QAClE,oBAAU,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,UAAU,IAAI,GAAG,UAAU;AAGnD,YAAM,UAAW,QAAQ,gBAAiB;AAC1C,aAAO,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACN,WAAU;AAAA,UAEV,OAAO;AAAA,YACL,yBAAyB,GAAG,GAAG;AAAA,YAC/B,2BAA2B,IAAI,OAAO;AAAA,YACtC,8BAA8B,GAAG,QAAQ;AAAA,YACzC,0BAA0B,GAAG,IAAI;AAAA,YACjC,6BAA6B;AAAA,YAC7B,2BAA2B,eAAe,YAAY;AAAA,UACxD;AAAA,UAEA,0BAAAA,KAAC,cAAW,QAAQ,cAAc;AAAA;AAAA,QAV7B,GAAG,YAAY,IAAI,KAAK;AAAA,MAW/B;AAAA,IACF,CAAC,GACH;AAAA,IAEF,gBAAAA,KAAC,SAAI,WAAW,WAAW,uCAAuC,gBAAgB,GAAI,UAAS;AAAA,KACjG;AAEJ;;;AC1OA;AAAA,EACE;AAAA,EACA,aAAAE;AAAA,EACA,UAAAC;AAAA,EACA,YAAAC;AAAA,OACK;AAgEP,IAAM,oBAAoB;AAC1B,IAAM,oBAAoB;AAC1B,IAAM,wBAAwB;AAC9B,IAAM,oBAAoB;AAE1B,SAAS,kBAAkB,OAAoB;AAC7C,MAAI,OAAO,aAAa,YAAa;AAErC,QAAM,OAAO,SAAS;AACtB,OAAK,UAAU,OAAO,QAAQ,UAAU,MAAM;AAC9C,OAAK,MAAM,cAAc;AAC3B;AAEA,SAAS,iBACP,YACA,cACA,qBACa;AACb,MAAI,OAAO,WAAW,YAAa,QAAO;AAE1C,MAAI;AACF,UAAM,SAAS,OAAO,aAAa,QAAQ,UAAU;AACrD,QAAI,WAAW,WAAW,WAAW,OAAQ,QAAO;AAAA,EACtD,QAAQ;AAAA,EAER;AAEA,MACE,uBACA,OAAO,aAAa,8BAA8B,EAAE,SACpD;AACA,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEA,SAAS,oBACP,SACe;AACf,QAAM,WAAW,oBAAI,IAAiB;AAEtC,aAAW,UAAU,SAAS;AAC5B,QAAI,CAAC,OAAQ;AAEb,UAAM,UACJ,OAAO,WAAW,YAAY,aAAa,SACvC,OAAO,UACP;AAEN,QAAI,QAAS,UAAS,IAAI,OAAO;AAAA,EACnC;AAEA,SAAO,CAAC,GAAG,QAAQ;AACrB;AAEO,SAAS,eAAe;AAAA,EAC7B,aAAa;AAAA,EACb,eAAe;AAAA,EACf,sBAAsB;AAAA,EACtB,YAAY;AAAA,EACZ,gBAAgB;AAAA,EAChB,WAAW;AAAA,EACX,cAAc;AAAA,EACd,aAAa;AAAA,EACb,OAAO;AAAA,EACP,eAAe,CAAC;AAAA,EAChB;AAAA,EACA;AACF,IAA2B,CAAC,GAAyB;AACnD,QAAM,CAAC,OAAO,aAAa,IAAIC;AAAA,IAAsB,MACnD,iBAAiB,YAAY,cAAc,mBAAmB;AAAA,EAChE;AACA,QAAM,CAAC,SAAS,UAAU,IAAIA,UAAS,KAAK;AAC5C,QAAM,CAAC,WAAW,YAAY,IAAIA,UAAS,KAAK;AAEhD,QAAM,WAAWC,QAAO,KAAK;AAC7B,QAAM,eAAeA,QAAO,KAAK;AACjC,QAAM,eAAeA,QAAsB,IAAI;AAC/C,QAAM,kBAAkBA,QAAsB,IAAI;AAClD,QAAM,gBAAgBA,QAAO,UAAU;AACvC,QAAM,UAAUA,QAAO,IAAI;AAC3B,QAAM,kBAAkBA,QAAO,YAAY;AAC3C,QAAM,gBAAgBA,QAAO,UAAU;AACvC,QAAM,mBAAmBA,QAAO,aAAa;AAC7C,QAAM,mBAAmBA,QAAsB,CAAC,CAAC;AACjD,QAAM,kBAAkBA,QAAiC,IAAI;AAC7D,QAAM,WAAWA,QAAgC,IAAI;AACrD,QAAM,cAAcA,QAAO,QAAQ;AACnC,QAAM,iBAAiBA,QAAO,WAAW;AAEzC,WAAS,UAAU;AACnB,gBAAc,UAAU;AACxB,UAAQ,UAAU;AAClB,kBAAgB,UAAU;AAC1B,gBAAc,UAAU;AACxB,mBAAiB,UAAU;AAC3B,cAAY,UAAU;AACtB,iBAAe,UAAU;AAEzB,QAAM,iBAAiB,YAAY,MAAM;AACvC,QAAI,OAAO,WAAW,eAAe,CAAC,YAAY,QAAS;AAE3D,QAAI;AACF,UAAI,CAAC,SAAS,WAAW,SAAS,QAAQ,QAAQ,IAAI,IAAI,YAAY,SAAS,SAAS,OAAO,EAAE,MAAM;AACrG,iBAAS,SAAS,MAAM;AACxB,iBAAS,SAAS,OAAO;AACzB,iBAAS,UAAU,IAAI,MAAM,YAAY,OAAO;AAChD,iBAAS,QAAQ,UAAU;AAC3B,iBAAS,QAAQ,aAAa,eAAe,MAAM;AACnD,iBAAS,QAAQ,MAAM,UAAU;AACjC,iBAAS,KAAK,YAAY,SAAS,OAAO;AAAA,MAC5C;AACA,YAAM,QAAQ,SAAS;AACvB,YAAM,SAAS,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,eAAe,OAAO,CAAC;AAC9D,YAAM,cAAc;AACpB,WAAK,MAAM,KAAK,EAAE,MAAM,MAAM;AAAA,MAE9B,CAAC;AAAA,IACH,QAAQ;AAAA,IAER;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,eAAe;AAAA,IACnB,CAAC,cAA2B;AAC1B,oBAAc,QAAQ,SAAS;AAC/B,oBAAc,SAAS;AACvB,eAAS,UAAU;AAEnB,UAAI;AACF,eAAO,aAAa,QAAQ,YAAY,SAAS;AAAA,MACnD,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,IACA,CAAC,UAAU;AAAA,EACb;AAEA,EAAAC,WAAU,MAAM;AACd,UAAM,eAAe;AAAA,MACnB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,aAAS,UAAU;AACnB,kBAAc,YAAY;AAC1B,kBAAc,QAAQ,YAAY;AAClC,eAAW,IAAI;AAAA,EACjB,GAAG,CAAC,cAAc,YAAY,mBAAmB,CAAC;AAElD,QAAM,cAAc,YAAY,MAAM;AACpC,QAAI,aAAa,YAAY,MAAM;AACjC,aAAO,aAAa,aAAa,OAAO;AACxC,mBAAa,UAAU;AAAA,IACzB;AAEA,QAAI,gBAAgB,YAAY,MAAM;AACpC,aAAO,aAAa,gBAAgB,OAAO;AAC3C,sBAAgB,UAAU;AAAA,IAC5B;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,eAAe,YAAY,MAAM;AACrC,QACE,OAAO,WAAW,eAClB,OAAO,aAAa,eACpB,gBAAgB,SAChB;AACA;AAAA,IACF;AAEA,UAAM,OAAO,SAAS;AACtB,UAAM,OAAO,SAAS;AACtB,UAAM,YAA+B;AAAA,MACnC,SAAS,OAAO;AAAA,MAChB,SAAS,OAAO;AAAA,MAChB,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,cAAc,KAAK,MAAM;AAAA,MACzB,cAAc,KAAK,MAAM;AAAA,MACzB,wBAAwB,KAAK,MAAM;AAAA,IACrC;AAEA,oBAAgB,UAAU;AAE1B,UAAM,mBAAmB,MAAM;AAC7B,UAAI,CAAC,UAAU,OAAQ;AACvB,aAAO,SAAS,UAAU,SAAS,UAAU,OAAO;AACpD,gBAAU,QAAQ,OAAO,sBAAsB,gBAAgB;AAAA,IACjE;AAEA,SAAK,UAAU,IAAI,iBAAiB;AACpC,SAAK,MAAM,WAAW;AACtB,SAAK,MAAM,qBAAqB;AAChC,SAAK,MAAM,WAAW;AACtB,cAAU,QAAQ,OAAO,sBAAsB,gBAAgB;AAAA,EACjE,GAAG,CAAC,CAAC;AAEL,QAAM,iBAAiB,YAAY,CAAC,gBAAyB;AAC3D,QAAI,OAAO,WAAW,eAAe,OAAO,aAAa,aAAa;AACpE;AAAA,IACF;AAEA,UAAM,YAAY,gBAAgB;AAClC,QAAI,CAAC,UAAW;AAEhB,cAAU,SAAS;AACnB,WAAO,qBAAqB,UAAU,KAAK;AAE3C,UAAM,OAAO,SAAS;AACtB,UAAM,OAAO,SAAS;AACtB,SAAK,MAAM,WAAW,UAAU;AAChC,SAAK,MAAM,WAAW,UAAU;AAChC,SAAK,MAAM,qBAAqB,UAAU;AAC1C,SAAK,UAAU,OAAO,iBAAiB;AAEvC,oBAAgB,UAAU;AAC1B,WAAO,SAAS,UAAU,SAAS,UAAU,OAAO;AAEpD,QAAI,aAAa;AACf,aAAO,sBAAsB,MAAM;AACjC,yBAAiB,UAAU;AAAA,MAC7B,CAAC;AAAA,IACH;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,qBAAqB,YAAY,MAAM;AAC3C,eAAW,UAAU,iBAAiB,SAAS;AAC7C,aAAO,UAAU;AAAA,QACf;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,aAAO,MAAM,eAAe,0BAA0B;AAAA,IACxD;AAEA,qBAAiB,UAAU,CAAC;AAAA,EAC9B,GAAG,CAAC,CAAC;AAEL,QAAM,eAAe,YAAY,MAAM;AACrC,QAAI,SAAS,SAAS;AACpB,eAAS,QAAQ,MAAM;AACvB,eAAS,QAAQ,cAAc;AAAA,IACjC;AACA,uBAAmB;AACnB,mBAAe,IAAI;AACnB,iBAAa,UAAU;AACvB,iBAAa,KAAK;AAAA,EACpB,GAAG,CAAC,oBAAoB,cAAc,CAAC;AAEvC,QAAM,WAAW;AAAA,IACf,CAAC,cAA2B;AAC1B,UAAI,aAAa,QAAS;AAC1B,mBAAa,SAAS;AAAA,IACxB;AAAA,IACA,CAAC,YAAY;AAAA,EACf;AAEA,QAAM,cAAc,YAAY,MAAM;AACpC,QACE,OAAO,WAAW,eAClB,OAAO,aAAa,eACpB,aAAa,SACb;AACA;AAAA,IACF;AAEA,mBAAe;AAEf,UAAM,cAAc,QAAQ;AAC5B,UAAM,mBACJ,cAAc,WAAW,gBAAgB;AAE3C,QAAI,gBAAgB,cAAc,kBAAkB;AAClD,mBAAa;AAAA,IACf;AAEA,UAAM,UACJ,gBAAgB,SACZ,CAAC,SAAS,IAAI,IACd,oBAAoB,gBAAgB,OAAO;AAEjD,UAAM,YACJ,gBAAgB,SACZ,oBACA;AAEN,eAAW,UAAU,SAAS;AAC5B,aAAO,MAAM;AAAA,QACX;AAAA,QACA,gBAAgB,SACZ,GAAG,OAAO,UAAU,OAAO,cAAc,CAAC,OAC1C;AAAA,MACN;AACA,aAAO,UAAU,IAAI,mBAAmB,SAAS;AAAA,IACnD;AAEA,qBAAiB,UAAU;AAC3B,iBAAa,UAAU;AACvB,iBAAa,IAAI;AAEjB,UAAM,gBAAgB,OAAO;AAAA,MAC3B;AAAA,IACF,EAAE;AAEF,UAAM,YACJ,SAAS,YAAY,SAAS,UAAU;AAE1C,UAAM,qBAAqB,gBACvB,KACA,KAAK,IAAI,GAAG,SAAS;AACzB,UAAM,oBAAoB,gBACtB,MACA,KAAK,IAAI,oBAAoB,aAAa;AAE9C,iBAAa,UAAU,OAAO,WAAW,MAAM;AAC7C,mBAAa,SAAS;AACtB,mBAAa,UAAU;AAAA,IACzB,GAAG,kBAAkB;AAErB,oBAAgB,UAAU,OAAO,WAAW,MAAM;AAChD,sBAAgB,UAAU;AAC1B,mBAAa;AAAA,IACf,GAAG,iBAAiB;AAAA,EACtB,GAAG,CAAC,cAAc,cAAc,cAAc,gBAAgB,WAAW,aAAa,CAAC;AAEvF,EAAAA,WAAU,MAAM;AACd,WAAO,MAAM;AACX,kBAAY;AACZ,yBAAmB;AACnB,qBAAe,KAAK;AACpB,eAAS,SAAS,MAAM;AACxB,eAAS,SAAS,OAAO;AACzB,UAAI,SAAS,QAAS,UAAS,QAAQ,cAAc;AACrD,eAAS,UAAU;AAAA,IACrB;AAAA,EACF,GAAG,CAAC,aAAa,oBAAoB,cAAc,CAAC;AAEpD,SAAO;AAAA,IACL;AAAA,IACA,QAAQ,UAAU;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":["useState","initialPixels","initialScale","visualCenter","portalCenterX","portalCenterY","useLayoutEffect","useState","jsx","useState","createPortal","jsx","jsxs","jsx","createPortal","useRef","Fragment","jsx","jsxs","useRef","jsx","jsx","useEffect","useState","jsx","jsxs","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.6",
3
+ "version": "0.5.1",
4
4
  "description": "Componentes, transiciones y recursos visuales oficiales del ecosistema WalrOS.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",