@beweco/aurora-ui 0.6.85 → 0.6.87

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.
Files changed (28) hide show
  1. package/dist/assets/css/styles.css +1 -1
  2. package/dist/index.cjs.js +643 -250
  3. package/dist/index.esm.js +641 -252
  4. package/dist/types/components/beta-badge/BetaBadge.d.ts +9 -0
  5. package/dist/types/components/beta-badge/BetaBadge.d.ts.map +1 -0
  6. package/dist/types/components/beta-badge/BetaBadge.types.d.ts +27 -0
  7. package/dist/types/components/beta-badge/BetaBadge.types.d.ts.map +1 -0
  8. package/dist/types/components/beta-badge/beta-badge.styles.d.ts +2 -0
  9. package/dist/types/components/beta-badge/beta-badge.styles.d.ts.map +1 -0
  10. package/dist/types/components/beta-badge/index.d.ts +3 -0
  11. package/dist/types/components/beta-badge/index.d.ts.map +1 -0
  12. package/dist/types/components/linda-mascot/LindaMascot.d.ts +17 -0
  13. package/dist/types/components/linda-mascot/LindaMascot.d.ts.map +1 -0
  14. package/dist/types/components/linda-mascot/LindaMascot.types.d.ts +56 -0
  15. package/dist/types/components/linda-mascot/LindaMascot.types.d.ts.map +1 -0
  16. package/dist/types/components/linda-mascot/index.d.ts +4 -0
  17. package/dist/types/components/linda-mascot/index.d.ts.map +1 -0
  18. package/dist/types/components/linda-mascot/linda-mascot.constants.d.ts +55 -0
  19. package/dist/types/components/linda-mascot/linda-mascot.constants.d.ts.map +1 -0
  20. package/dist/types/components/linda-mascot/linda-mascot.styles.d.ts +2 -0
  21. package/dist/types/components/linda-mascot/linda-mascot.styles.d.ts.map +1 -0
  22. package/dist/types/index.d.ts +2 -0
  23. package/dist/types/index.d.ts.map +1 -1
  24. package/dist/types/utils/theme-scope.d.ts +18 -0
  25. package/dist/types/utils/theme-scope.d.ts.map +1 -0
  26. package/dist/types/utils/use-injected-style.d.ts +25 -0
  27. package/dist/types/utils/use-injected-style.d.ts.map +1 -0
  28. package/package.json +1 -1
package/dist/index.cjs.js CHANGED
@@ -794,263 +794,49 @@ var AuraAutocomplete = function (_a) {
794
794
  };
795
795
 
796
796
  /**
797
- * ColorPicker Types
797
+ * Deja una `<style id>` en el `<head>` con las reglas de un componente, una sola vez.
798
798
  *
799
- * Defines the type system for the ColorPicker component used for brand configuration.
800
- */
801
- /**
802
- * Default predefined colors (Brand-safe palette)
803
- */
804
- var DEFAULT_PREDEFINED_COLORS = [
805
- // Primary colors
806
- { key: "blue", name: "Azul", value: "#3B82F6" },
807
- { key: "violet", name: "Violeta", value: "#8B5CF6" },
808
- { key: "purple", name: "Púrpura", value: "#A855F7" },
809
- // Secondary colors
810
- { key: "green", name: "Verde", value: "#10B981" },
811
- { key: "teal", name: "Turquesa", value: "#14B8A6" },
812
- { key: "cyan", name: "Cian", value: "#06B6D4" },
813
- // Accent colors
814
- { key: "pink", name: "Rosa", value: "#EC4899" },
815
- { key: "rose", name: "Rosa claro", value: "#F43F5E" },
816
- { key: "orange", name: "Naranja", value: "#F97316" },
817
- // Neutral colors
818
- { key: "red", name: "Rojo", value: "#EF4444" },
819
- { key: "amber", name: "Ámbar", value: "#F59E0B" },
820
- { key: "yellow", name: "Amarillo", value: "#EAB308" },
821
- // Gray scale (useful for text/backgrounds)
822
- { key: "gray-dark", name: "Gris oscuro", value: "#374151" },
823
- { key: "gray", name: "Gris", value: "#6B7280" },
824
- { key: "gray-light", name: "Gris claro", value: "#9CA3AF" },
825
- ];
826
-
827
- /**
828
- * Default translations (Spanish)
829
- */
830
- var defaultTranslations$e = {
831
- label: "Color",
832
- placeholder: "Ingresa código hex",
833
- customColorLabel: "Color personalizado",
834
- predefinedColorsLabel: "Colores predefinidos",
835
- recentColorsLabel: "Colores recientes",
836
- noRecentColors: "No hay colores recientes",
837
- invalidColorFormat: "El código de color no es un formato HEX válido (Ej: #FF5733 o FFA07A)",
838
- colorPreview: "Vista previa del color",
839
- };
840
- /**
841
- * Validates hex color format (#RRGGBB or #RGB)
842
- */
843
- var isValidHexColor = function (color) {
844
- var hexRegex = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/;
845
- return hexRegex.test(color);
846
- };
847
- /**
848
- * Normalizes hex color to 6-digit format (#RGB -> #RRGGBB)
799
+ * Existe para los componentes que no pueden depender de `@beweco/aurora-ui/styles`: los
800
+ * que llegan a un microfrontend por Module Federation (chatbot-claw recibe aurora-ui del
801
+ * host con `import: false`) o se montan sueltos. Si sus reglas vivieran en `styles.css`,
802
+ * funcionarían solo cuando el host carga ese CSS y además en la misma versión que el JS
803
+ * que viaja por MF; cuando no, el componente sale sin animación ni tema y nadie se entera.
804
+ * Aquí la regla viaja con el componente, como ya hace `SocialMediaCarousel`.
805
+ *
806
+ * Idempotente por `id`: cien mascotas en un hilo dejan una sola `<style>`. Nunca reescribe
807
+ * una `<style>` existente: si en la página conviven dos copias del paquete, se pisarían en
808
+ * cada montaje. Para que una versión nueva del CSS entre, el id lleva su huella
809
+ * (`styleIdFor`).
849
810
  */
850
- var normalizeHexColor = function (color) {
851
- if (!color.startsWith("#")) {
852
- color = "#".concat(color);
811
+ var injectStyle = function (doc, id, css) {
812
+ if (!(doc === null || doc === void 0 ? void 0 : doc.head)) {
813
+ return;
853
814
  }
854
- // Convert 3-digit to 6-digit
855
- if (color.length === 4) {
856
- var r = color[1];
857
- var g = color[2];
858
- var b = color[3];
859
- return "#".concat(r).concat(r).concat(g).concat(g).concat(b).concat(b).toUpperCase();
815
+ if (doc.getElementById(id)) {
816
+ return;
860
817
  }
861
- return color.toUpperCase();
818
+ var style = doc.createElement("style");
819
+ style.id = id;
820
+ style.textContent = css;
821
+ doc.head.appendChild(style);
822
+ };
823
+ /** `<base>-<huella del css>`: estable para el mismo CSS, distinto si cambia. */
824
+ var styleIdFor = function (base, css) {
825
+ var hash = 5381;
826
+ for (var i = 0; i < css.length; i++) {
827
+ hash = ((hash << 5) + hash + css.charCodeAt(i)) | 0;
828
+ }
829
+ return "".concat(base, "-").concat((hash >>> 0).toString(36));
862
830
  };
863
831
  /**
864
- * Strips leading "#" characters so the text input shows only the hex digits.
865
- * The "#" prefix is rendered as a fixed startContent in the Input.
866
- */
867
- var stripHash = function (color) { return color.replace(/^#+/, ""); };
868
- /**
869
- * ColorPicker - Advanced color selection component
870
- *
871
- * Features:
872
- * - Native color picker input
873
- * - Text input for hex codes
874
- * - Predefined color palette
875
- * - Recent colors with localStorage persistence
876
- * - Full i18n support
877
- * - Dark mode compatible
878
- * - Accessible
879
- *
880
- * @component
881
- * @example
882
- * ```tsx
883
- * <ColorPicker
884
- * value={brandColor}
885
- * onChange={setBrandColor}
886
- * label="Color de marca"
887
- * enableRecentColors
888
- * />
889
- * ```
832
+ * `useInsertionEffect` corre antes de pintar y antes que los efectos de layout: las reglas
833
+ * están en el documento cuando el SVG aparece por primera vez, sin parpadeo sin estilo.
834
+ * En servidor no corre (y `renderToStaticMarkup` en los tests tampoco lo ejecuta).
890
835
  */
891
- var ColorPicker = React.forwardRef(function (_a, ref) {
892
- var value = _a.value, onChange = _a.onChange, label = _a.label, _b = _a.required, required = _b === void 0 ? false : _b, _c = _a.disabled, disabled = _c === void 0 ? false : _c, _d = _a.error, error = _d === void 0 ? false : _d, errorText = _a.errorText, _e = _a.predefinedColors, predefinedColors = _e === void 0 ? DEFAULT_PREDEFINED_COLORS : _e, _f = _a.enableRecentColors, enableRecentColors = _f === void 0 ? true : _f, _g = _a.maxRecentColors, maxRecentColors = _g === void 0 ? 6 : _g, _h = _a.recentColorsStorageKey, recentColorsStorageKey = _h === void 0 ? "aurora-ui-recent-colors" : _h, _j = _a.showPredefinedColors, showPredefinedColors = _j === void 0 ? true : _j, _k = _a.translations, translations = _k === void 0 ? {} : _k, _l = _a.className, className = _l === void 0 ? "" : _l, id = _a.id, name = _a.name;
893
- var generatedId = React.useId();
894
- var inputId = id || generatedId;
895
- var t = __assign(__assign({}, defaultTranslations$e), translations);
896
- // Local state for text input — holds the hex digits WITHOUT the leading "#".
897
- // The "#" is rendered as a fixed startContent prefix.
898
- var _m = React.useState(stripHash(value)), textValue = _m[0], setTextValue = _m[1];
899
- var _o = React.useState(false), isInvalidFormat = _o[0], setIsInvalidFormat = _o[1];
900
- // Recent colors state
901
- var _p = React.useState([]), recentColors = _p[0], setRecentColors = _p[1];
902
- // Load recent colors from localStorage on mount
903
- React.useEffect(function () {
904
- if (!enableRecentColors)
905
- return;
906
- try {
907
- var stored = localStorage.getItem(recentColorsStorageKey);
908
- if (stored) {
909
- var colors = JSON.parse(stored);
910
- setRecentColors(colors);
911
- }
912
- }
913
- catch (error) {
914
- console.error("Error loading recent colors:", error);
915
- }
916
- }, [enableRecentColors, recentColorsStorageKey]);
917
- // Save to recent colors when value changes
918
- React.useEffect(function () {
919
- if (!enableRecentColors || !value || !isValidHexColor(value))
920
- return;
921
- var normalizedValue = normalizeHexColor(value);
922
- // Add to recent colors if not already present
923
- setRecentColors(function (prev) {
924
- // Remove if already exists
925
- var filtered = prev.filter(function (c) { return c !== normalizedValue; });
926
- // Add to beginning
927
- var updated = __spreadArray([normalizedValue], filtered, true).slice(0, maxRecentColors);
928
- // Save to localStorage
929
- try {
930
- localStorage.setItem(recentColorsStorageKey, JSON.stringify(updated));
931
- }
932
- catch (error) {
933
- console.error("Error saving recent colors:", error);
934
- }
935
- return updated;
936
- });
937
- }, [value, enableRecentColors, maxRecentColors, recentColorsStorageKey]);
938
- // Sync text value when prop value changes
939
- React.useEffect(function () {
940
- setTextValue(stripHash(value));
941
- setIsInvalidFormat(false);
942
- }, [value]);
943
- /**
944
- * Handle color picker (native input) change
945
- */
946
- var handleColorPickerChange = function (e) {
947
- var newColor = normalizeHexColor(e.target.value);
948
- setTextValue(stripHash(newColor));
949
- setIsInvalidFormat(false);
950
- onChange(newColor);
951
- };
952
- /**
953
- * Handle text input change — passive: no validation, normalization, or
954
- * onChange propagation while typing. We only update local state and clear
955
- * any stale error so the user can correct an invalid value without the
956
- * red border lingering. Validation (and stripping of the leading "#")
957
- * runs on blur.
958
- *
959
- * While typing we let the user see whatever they pressed — including a
960
- * leading "#" — so the input feels responsive. To prevent a double "#"
961
- * on screen, the fixed prefix in `startContent` is hidden while
962
- * `textValue` already starts with "#". The cap is `7` (1 "#" + 6 hex)
963
- * when the user opted into a leading "#", otherwise `6`.
964
- */
965
- var handleTextChange = function (newValue) {
966
- var max = newValue.startsWith("#") ? 7 : 6;
967
- setTextValue(newValue.slice(0, max));
968
- setIsInvalidFormat(false);
969
- };
970
- /**
971
- * Validate the current hex input. Updates `isInvalidFormat` and, when
972
- * the input is a valid hex, normalizes the display and propagates via
973
- * `onChange`. Returns whether the input is acceptable so a caller can
974
- * decide to block submission.
975
- *
976
- * Empty + not required → valid (no error, no propagation).
977
- * Empty + required → invalid (error).
978
- * Valid (3 or 6 hex chars, with or without leading "#") → normalize, sync
979
- * display to canonical form, propagate, valid.
980
- * Otherwise → invalid (error, no propagation).
981
- */
982
- var validate = React.useCallback(function () {
983
- // User may have typed a leading "#" — strip it so it doesn't end up
984
- // as "##" once we prepend "#" for the regex check.
985
- var trimmed = stripHash(textValue.trim());
986
- if (trimmed === "") {
987
- var valid = !required;
988
- setIsInvalidFormat(!valid);
989
- // Drop any residual "#" the user typed but never followed up on,
990
- // so the field reads as truly empty after blur.
991
- setTextValue("");
992
- return valid;
993
- }
994
- var candidate = "#".concat(trimmed);
995
- if (!isValidHexColor(candidate)) {
996
- setIsInvalidFormat(true);
997
- return false;
998
- }
999
- var normalized = normalizeHexColor(candidate);
1000
- setIsInvalidFormat(false);
1001
- setTextValue(stripHash(normalized));
1002
- onChange(normalized);
1003
- return true;
1004
- }, [textValue, required, onChange]);
1005
- React.useImperativeHandle(ref, function () { return ({ validate: validate }); }, [validate]);
1006
- var handleTextBlur = function () {
1007
- validate();
1008
- };
1009
- /**
1010
- * Handle predefined color selection
1011
- */
1012
- var handlePredefinedColorClick = function (colorValue) {
1013
- if (disabled)
1014
- return;
1015
- var normalized = normalizeHexColor(colorValue);
1016
- setTextValue(stripHash(normalized));
1017
- setIsInvalidFormat(false);
1018
- onChange(normalized);
1019
- };
1020
- /**
1021
- * Render a color circle button
1022
- */
1023
- var renderColorCircle = function (colorValue, colorName, isSelected) { return (jsxRuntime.jsx("button", { type: "button", disabled: disabled, onClick: function () { return handlePredefinedColorClick(colorValue); }, className: "\n\t\t\t\tw-8 h-8 rounded-full border-2 cursor-pointer transition-all\n\t\t\t\tfocus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-1\n\t\t\t\t".concat(disabled ? "opacity-50 cursor-not-allowed" : "hover:scale-110", "\n\t\t\t\t").concat(isSelected
1024
- ? "border-primary-500 scale-110 ring-2 ring-primary-500 ring-offset-1"
1025
- : "border-default-700", "\n\t\t\t"), style: { backgroundColor: colorValue }, title: colorName, "aria-label": colorName }, colorValue)); };
1026
- return (jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 ".concat(className), children: [label && (jsxRuntime.jsxs("label", { htmlFor: inputId, className: "block text-sm font-medium text-foreground", children: [label, required && jsxRuntime.jsx("span", { className: "text-danger ml-1", children: "*" })] })), jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [jsxRuntime.jsx("input", { type: "color", id: inputId, name: name, value: "#".concat(stripHash(textValue)), onChange: handleColorPickerChange, disabled: disabled, className: "\n\t\t\t\t\t\t\tw-10 h-10 rounded-lg cursor-pointer border-2 flex-shrink-0\n\t\t\t\t\t\t\ttransition-colors appearance-none bg-transparent p-0.5\n\t\t\t\t\t\t\tfocus:border-primary-500\n\t\t\t\t\t\t\t".concat(disabled ? "opacity-50 cursor-not-allowed" : "hover:border-default-400", "\n\t\t\t\t\t\t\t").concat(error
1027
- ? "border-danger dark:border-danger-400"
1028
- : "border-default-300 dark:border-default-700", "\n\t\t\t\t\t\t"), "aria-label": t.customColorLabel, title: t.customColorLabel }), jsxRuntime.jsx(react.Input, { type: "text", value: textValue, onValueChange: handleTextChange, onBlur: handleTextBlur, placeholder: t.placeholder, disabled: disabled, isInvalid: error || isInvalidFormat, size: "sm", variant: "bordered", classNames: {
1029
- input: "uppercase font-mono text-small",
1030
- inputWrapper: "min-h-8 h-8 focus-within:!border-primary-500",
1031
- }, startContent: textValue.startsWith("#") ? null : (jsxRuntime.jsx("span", { className: "text-default-400 text-sm", children: "#" })) })] }), (error || isInvalidFormat) && (jsxRuntime.jsx("p", { className: "text-tiny text-danger", children: isInvalidFormat ? t.invalidColorFormat : errorText }))] }), showPredefinedColors && predefinedColors.length > 0 && (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("p", { className: "text-xs font-medium text-default-600 mb-2", children: t.predefinedColorsLabel }), jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: predefinedColors.map(function (color) {
1032
- return renderColorCircle(color.value, color.name, normalizeHexColor(value) === normalizeHexColor(color.value));
1033
- }) })] })), enableRecentColors && recentColors.length > 0 && (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("p", { className: "text-xs font-medium text-default-600 mb-2", children: t.recentColorsLabel }), jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: recentColors.map(function (color) {
1034
- return renderColorCircle(color, color, normalizeHexColor(value) === color);
1035
- }) })] }))] }));
1036
- });
1037
- ColorPicker.displayName = "ColorPicker";
1038
-
1039
- var ThemeContext = React.createContext({
1040
- mode: "light",
1041
- color: "blue",
1042
- customHex: null,
1043
- // biome-ignore lint/suspicious/noEmptyBlockStatements: <explanation>
1044
- setMode: function () { },
1045
- // biome-ignore lint/suspicious/noEmptyBlockStatements: <explanation>
1046
- setColor: function () { },
1047
- });
1048
- var useThemeContext = function () {
1049
- var context = React.useContext(ThemeContext);
1050
- if (!context) {
1051
- throw new Error("useThemeContext debe ser usado dentro de un ThemeProvider");
1052
- }
1053
- return context;
836
+ var useInjectedStyle = function (id, css) {
837
+ React.useInsertionEffect(function () {
838
+ injectStyle(typeof document === "undefined" ? undefined : document, id, css);
839
+ }, [id, css]);
1054
840
  };
1055
841
 
1056
842
  var themeColors = {
@@ -1851,6 +1637,338 @@ var themeColors = {
1851
1637
  },
1852
1638
  };
1853
1639
 
1640
+ var namesOf = function (mode) { return __spreadArray([
1641
+ ".".concat(mode),
1642
+ "[data-theme=\"".concat(mode, "\"]")
1643
+ ], Object.entries(themeColors)
1644
+ .filter(function (_a) {
1645
+ var theme = _a[1];
1646
+ return theme.extend === mode;
1647
+ })
1648
+ .map(function (_a) {
1649
+ var name = _a[0];
1650
+ return ".".concat(name);
1651
+ }), true); };
1652
+ /**
1653
+ * Selectores para que un componente con `appearance="auto"` siga al tema del ancestro MÁS
1654
+ * CERCANO.
1655
+ *
1656
+ * Los temas no solo se llaman `dark`/`light`: el `ThemeProvider` de esta librería pone en
1657
+ * `<html>` el tema completo (`blue-dark`, `purple-light`…) y nunca la clase `dark` suelta,
1658
+ * así que mirar solo `.dark` dejaría la pieza en claro sobre un tema oscuro de aurora.
1659
+ *
1660
+ * - `dark`: cualquier ancestro oscuro, o uno oscuro dentro de uno claro.
1661
+ * - `light`: uno claro dentro de uno oscuro (un panel claro en una página oscura). Tiene
1662
+ * una clase más que el oscuro simple, así que gana; va después en la hoja para ganar
1663
+ * también al «oscuro dentro de claro» cuando hay tres niveles.
1664
+ */
1665
+ var themeScopeSelectors = function (target) {
1666
+ var dark = namesOf("dark");
1667
+ var light = namesOf("light");
1668
+ var pairs = function (outer, inner) {
1669
+ return outer.flatMap(function (o) { return inner.map(function (i) { return "".concat(o, " ").concat(i, " ").concat(target); }); });
1670
+ };
1671
+ return {
1672
+ dark: __spreadArray(__spreadArray([], dark.map(function (d) { return "".concat(d, " ").concat(target); }), true), pairs(light, dark), true).join(",\n"),
1673
+ light: pairs(dark, light).join(",\n"),
1674
+ };
1675
+ };
1676
+
1677
+ /**
1678
+ * Reglas del sello Beta. Viajan con el componente (se inyectan en `<head>`), igual que las
1679
+ * de `LindaMascot`: el sello también se pinta dentro del microfrontend del chat.
1680
+ *
1681
+ * Borde de 1 px con el gradiente iridiscente de la mascota muy atenuado: dos fondos, el
1682
+ * neutro recortado al `padding-box` y el gradiente al `border-box`, con el borde
1683
+ * transparente para que se vea el de debajo. Es neutral de marca: lo verá también Luna.
1684
+ */
1685
+ var AUTO_THEME$1 = themeScopeSelectors('.aurora-beta-badge[data-appearance="auto"]');
1686
+ var BETA_BADGE_CSS = "\n.aurora-beta-badge {\n\t--bb-bg: #F6F5FB;\n\t--bb-fg: #4B4F6E;\n\t--bb-edge: 52%;\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\tbox-sizing: border-box;\n\tborder: 1px solid transparent;\n\tborder-radius: 999px;\n\tbackground:\n\t\tlinear-gradient(var(--bb-bg), var(--bb-bg)) padding-box,\n\t\tlinear-gradient(\n\t\t\t100deg,\n\t\t\tcolor-mix(in srgb, #FF8AD8 var(--bb-edge), var(--bb-bg)),\n\t\t\tcolor-mix(in srgb, #A48BFF var(--bb-edge), var(--bb-bg)) 38%,\n\t\t\tcolor-mix(in srgb, #6FE3FF var(--bb-edge), var(--bb-bg)) 70%,\n\t\t\tcolor-mix(in srgb, #FFD08A var(--bb-edge), var(--bb-bg))\n\t\t) border-box;\n\tcolor: var(--bb-fg);\n\tfont-family: inherit;\n\tfont-weight: 600;\n\tline-height: 1;\n\tletter-spacing: 0.06em;\n\ttext-transform: uppercase;\n\twhite-space: nowrap;\n\tvertical-align: middle;\n\tuser-select: none;\n\tflex-shrink: 0;\n}\n/* Tema: sigue al ancestro claro/oscuro m\u00E1s cercano (ver `themeScopeSelectors`). */\n".concat(AUTO_THEME$1.dark, ",\n.aurora-beta-badge[data-appearance=\"dark\"] {\n\t--bb-bg: #1C1D30;\n\t--bb-fg: #D5D8F0;\n\t--bb-edge: 58%;\n}\n").concat(AUTO_THEME$1.light, " {\n\t--bb-bg: #F6F5FB;\n\t--bb-fg: #4B4F6E;\n\t--bb-edge: 52%;\n}\n.aurora-beta-badge--sm {\n\tfont-size: 10px;\n\theight: 16px;\n\tpadding: 0 6px 0 calc(6px + 0.06em);\n}\n.aurora-beta-badge--md {\n\tfont-size: 11px;\n\theight: 18px;\n\tpadding: 0 7px 0 calc(7px + 0.06em);\n}\n");
1687
+
1688
+ var DEFAULT_TRANSLATIONS$c = {
1689
+ label: "Beta",
1690
+ title: "Funcionalidad en pruebas: puede cambiar",
1691
+ };
1692
+ var BETA_BADGE_STYLE_ID = styleIdFor("aurora-beta-badge-styles", BETA_BADGE_CSS);
1693
+ /**
1694
+ * BetaBadge — sello «Beta» para lo que está en pruebas con clientes reales (Linda Claw).
1695
+ * Píldora pequeña en mayúsculas con el borde iridiscente de la mascota muy atenuado.
1696
+ * Ver README.
1697
+ */
1698
+ var BetaBadge = React.forwardRef(function BetaBadge(_a, ref) {
1699
+ var _b = _a.size, size = _b === void 0 ? "sm" : _b, title = _a.title, _c = _a.appearance, appearance = _c === void 0 ? "auto" : _c, translations = _a.translations, className = _a.className, spanProps = __rest(_a, ["size", "title", "appearance", "translations", "className"]);
1700
+ useInjectedStyle(BETA_BADGE_STYLE_ID, BETA_BADGE_CSS);
1701
+ var t = __assign(__assign({}, DEFAULT_TRANSLATIONS$c), translations);
1702
+ var tooltip = title === true ? t.title : title || undefined;
1703
+ return (jsxRuntime.jsx("span", __assign({ ref: ref, className: [
1704
+ "aurora-beta-badge",
1705
+ "aurora-beta-badge--".concat(size),
1706
+ className,
1707
+ ]
1708
+ .filter(Boolean)
1709
+ .join(" "), "data-appearance": appearance, title: tooltip }, spanProps, { children: t.label })));
1710
+ });
1711
+
1712
+ /**
1713
+ * ColorPicker Types
1714
+ *
1715
+ * Defines the type system for the ColorPicker component used for brand configuration.
1716
+ */
1717
+ /**
1718
+ * Default predefined colors (Brand-safe palette)
1719
+ */
1720
+ var DEFAULT_PREDEFINED_COLORS = [
1721
+ // Primary colors
1722
+ { key: "blue", name: "Azul", value: "#3B82F6" },
1723
+ { key: "violet", name: "Violeta", value: "#8B5CF6" },
1724
+ { key: "purple", name: "Púrpura", value: "#A855F7" },
1725
+ // Secondary colors
1726
+ { key: "green", name: "Verde", value: "#10B981" },
1727
+ { key: "teal", name: "Turquesa", value: "#14B8A6" },
1728
+ { key: "cyan", name: "Cian", value: "#06B6D4" },
1729
+ // Accent colors
1730
+ { key: "pink", name: "Rosa", value: "#EC4899" },
1731
+ { key: "rose", name: "Rosa claro", value: "#F43F5E" },
1732
+ { key: "orange", name: "Naranja", value: "#F97316" },
1733
+ // Neutral colors
1734
+ { key: "red", name: "Rojo", value: "#EF4444" },
1735
+ { key: "amber", name: "Ámbar", value: "#F59E0B" },
1736
+ { key: "yellow", name: "Amarillo", value: "#EAB308" },
1737
+ // Gray scale (useful for text/backgrounds)
1738
+ { key: "gray-dark", name: "Gris oscuro", value: "#374151" },
1739
+ { key: "gray", name: "Gris", value: "#6B7280" },
1740
+ { key: "gray-light", name: "Gris claro", value: "#9CA3AF" },
1741
+ ];
1742
+
1743
+ /**
1744
+ * Default translations (Spanish)
1745
+ */
1746
+ var defaultTranslations$e = {
1747
+ label: "Color",
1748
+ placeholder: "Ingresa código hex",
1749
+ customColorLabel: "Color personalizado",
1750
+ predefinedColorsLabel: "Colores predefinidos",
1751
+ recentColorsLabel: "Colores recientes",
1752
+ noRecentColors: "No hay colores recientes",
1753
+ invalidColorFormat: "El código de color no es un formato HEX válido (Ej: #FF5733 o FFA07A)",
1754
+ colorPreview: "Vista previa del color",
1755
+ };
1756
+ /**
1757
+ * Validates hex color format (#RRGGBB or #RGB)
1758
+ */
1759
+ var isValidHexColor = function (color) {
1760
+ var hexRegex = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/;
1761
+ return hexRegex.test(color);
1762
+ };
1763
+ /**
1764
+ * Normalizes hex color to 6-digit format (#RGB -> #RRGGBB)
1765
+ */
1766
+ var normalizeHexColor = function (color) {
1767
+ if (!color.startsWith("#")) {
1768
+ color = "#".concat(color);
1769
+ }
1770
+ // Convert 3-digit to 6-digit
1771
+ if (color.length === 4) {
1772
+ var r = color[1];
1773
+ var g = color[2];
1774
+ var b = color[3];
1775
+ return "#".concat(r).concat(r).concat(g).concat(g).concat(b).concat(b).toUpperCase();
1776
+ }
1777
+ return color.toUpperCase();
1778
+ };
1779
+ /**
1780
+ * Strips leading "#" characters so the text input shows only the hex digits.
1781
+ * The "#" prefix is rendered as a fixed startContent in the Input.
1782
+ */
1783
+ var stripHash = function (color) { return color.replace(/^#+/, ""); };
1784
+ /**
1785
+ * ColorPicker - Advanced color selection component
1786
+ *
1787
+ * Features:
1788
+ * - Native color picker input
1789
+ * - Text input for hex codes
1790
+ * - Predefined color palette
1791
+ * - Recent colors with localStorage persistence
1792
+ * - Full i18n support
1793
+ * - Dark mode compatible
1794
+ * - Accessible
1795
+ *
1796
+ * @component
1797
+ * @example
1798
+ * ```tsx
1799
+ * <ColorPicker
1800
+ * value={brandColor}
1801
+ * onChange={setBrandColor}
1802
+ * label="Color de marca"
1803
+ * enableRecentColors
1804
+ * />
1805
+ * ```
1806
+ */
1807
+ var ColorPicker = React.forwardRef(function (_a, ref) {
1808
+ var value = _a.value, onChange = _a.onChange, label = _a.label, _b = _a.required, required = _b === void 0 ? false : _b, _c = _a.disabled, disabled = _c === void 0 ? false : _c, _d = _a.error, error = _d === void 0 ? false : _d, errorText = _a.errorText, _e = _a.predefinedColors, predefinedColors = _e === void 0 ? DEFAULT_PREDEFINED_COLORS : _e, _f = _a.enableRecentColors, enableRecentColors = _f === void 0 ? true : _f, _g = _a.maxRecentColors, maxRecentColors = _g === void 0 ? 6 : _g, _h = _a.recentColorsStorageKey, recentColorsStorageKey = _h === void 0 ? "aurora-ui-recent-colors" : _h, _j = _a.showPredefinedColors, showPredefinedColors = _j === void 0 ? true : _j, _k = _a.translations, translations = _k === void 0 ? {} : _k, _l = _a.className, className = _l === void 0 ? "" : _l, id = _a.id, name = _a.name;
1809
+ var generatedId = React.useId();
1810
+ var inputId = id || generatedId;
1811
+ var t = __assign(__assign({}, defaultTranslations$e), translations);
1812
+ // Local state for text input — holds the hex digits WITHOUT the leading "#".
1813
+ // The "#" is rendered as a fixed startContent prefix.
1814
+ var _m = React.useState(stripHash(value)), textValue = _m[0], setTextValue = _m[1];
1815
+ var _o = React.useState(false), isInvalidFormat = _o[0], setIsInvalidFormat = _o[1];
1816
+ // Recent colors state
1817
+ var _p = React.useState([]), recentColors = _p[0], setRecentColors = _p[1];
1818
+ // Load recent colors from localStorage on mount
1819
+ React.useEffect(function () {
1820
+ if (!enableRecentColors)
1821
+ return;
1822
+ try {
1823
+ var stored = localStorage.getItem(recentColorsStorageKey);
1824
+ if (stored) {
1825
+ var colors = JSON.parse(stored);
1826
+ setRecentColors(colors);
1827
+ }
1828
+ }
1829
+ catch (error) {
1830
+ console.error("Error loading recent colors:", error);
1831
+ }
1832
+ }, [enableRecentColors, recentColorsStorageKey]);
1833
+ // Save to recent colors when value changes
1834
+ React.useEffect(function () {
1835
+ if (!enableRecentColors || !value || !isValidHexColor(value))
1836
+ return;
1837
+ var normalizedValue = normalizeHexColor(value);
1838
+ // Add to recent colors if not already present
1839
+ setRecentColors(function (prev) {
1840
+ // Remove if already exists
1841
+ var filtered = prev.filter(function (c) { return c !== normalizedValue; });
1842
+ // Add to beginning
1843
+ var updated = __spreadArray([normalizedValue], filtered, true).slice(0, maxRecentColors);
1844
+ // Save to localStorage
1845
+ try {
1846
+ localStorage.setItem(recentColorsStorageKey, JSON.stringify(updated));
1847
+ }
1848
+ catch (error) {
1849
+ console.error("Error saving recent colors:", error);
1850
+ }
1851
+ return updated;
1852
+ });
1853
+ }, [value, enableRecentColors, maxRecentColors, recentColorsStorageKey]);
1854
+ // Sync text value when prop value changes
1855
+ React.useEffect(function () {
1856
+ setTextValue(stripHash(value));
1857
+ setIsInvalidFormat(false);
1858
+ }, [value]);
1859
+ /**
1860
+ * Handle color picker (native input) change
1861
+ */
1862
+ var handleColorPickerChange = function (e) {
1863
+ var newColor = normalizeHexColor(e.target.value);
1864
+ setTextValue(stripHash(newColor));
1865
+ setIsInvalidFormat(false);
1866
+ onChange(newColor);
1867
+ };
1868
+ /**
1869
+ * Handle text input change — passive: no validation, normalization, or
1870
+ * onChange propagation while typing. We only update local state and clear
1871
+ * any stale error so the user can correct an invalid value without the
1872
+ * red border lingering. Validation (and stripping of the leading "#")
1873
+ * runs on blur.
1874
+ *
1875
+ * While typing we let the user see whatever they pressed — including a
1876
+ * leading "#" — so the input feels responsive. To prevent a double "#"
1877
+ * on screen, the fixed prefix in `startContent` is hidden while
1878
+ * `textValue` already starts with "#". The cap is `7` (1 "#" + 6 hex)
1879
+ * when the user opted into a leading "#", otherwise `6`.
1880
+ */
1881
+ var handleTextChange = function (newValue) {
1882
+ var max = newValue.startsWith("#") ? 7 : 6;
1883
+ setTextValue(newValue.slice(0, max));
1884
+ setIsInvalidFormat(false);
1885
+ };
1886
+ /**
1887
+ * Validate the current hex input. Updates `isInvalidFormat` and, when
1888
+ * the input is a valid hex, normalizes the display and propagates via
1889
+ * `onChange`. Returns whether the input is acceptable so a caller can
1890
+ * decide to block submission.
1891
+ *
1892
+ * Empty + not required → valid (no error, no propagation).
1893
+ * Empty + required → invalid (error).
1894
+ * Valid (3 or 6 hex chars, with or without leading "#") → normalize, sync
1895
+ * display to canonical form, propagate, valid.
1896
+ * Otherwise → invalid (error, no propagation).
1897
+ */
1898
+ var validate = React.useCallback(function () {
1899
+ // User may have typed a leading "#" — strip it so it doesn't end up
1900
+ // as "##" once we prepend "#" for the regex check.
1901
+ var trimmed = stripHash(textValue.trim());
1902
+ if (trimmed === "") {
1903
+ var valid = !required;
1904
+ setIsInvalidFormat(!valid);
1905
+ // Drop any residual "#" the user typed but never followed up on,
1906
+ // so the field reads as truly empty after blur.
1907
+ setTextValue("");
1908
+ return valid;
1909
+ }
1910
+ var candidate = "#".concat(trimmed);
1911
+ if (!isValidHexColor(candidate)) {
1912
+ setIsInvalidFormat(true);
1913
+ return false;
1914
+ }
1915
+ var normalized = normalizeHexColor(candidate);
1916
+ setIsInvalidFormat(false);
1917
+ setTextValue(stripHash(normalized));
1918
+ onChange(normalized);
1919
+ return true;
1920
+ }, [textValue, required, onChange]);
1921
+ React.useImperativeHandle(ref, function () { return ({ validate: validate }); }, [validate]);
1922
+ var handleTextBlur = function () {
1923
+ validate();
1924
+ };
1925
+ /**
1926
+ * Handle predefined color selection
1927
+ */
1928
+ var handlePredefinedColorClick = function (colorValue) {
1929
+ if (disabled)
1930
+ return;
1931
+ var normalized = normalizeHexColor(colorValue);
1932
+ setTextValue(stripHash(normalized));
1933
+ setIsInvalidFormat(false);
1934
+ onChange(normalized);
1935
+ };
1936
+ /**
1937
+ * Render a color circle button
1938
+ */
1939
+ var renderColorCircle = function (colorValue, colorName, isSelected) { return (jsxRuntime.jsx("button", { type: "button", disabled: disabled, onClick: function () { return handlePredefinedColorClick(colorValue); }, className: "\n\t\t\t\tw-8 h-8 rounded-full border-2 cursor-pointer transition-all\n\t\t\t\tfocus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-1\n\t\t\t\t".concat(disabled ? "opacity-50 cursor-not-allowed" : "hover:scale-110", "\n\t\t\t\t").concat(isSelected
1940
+ ? "border-primary-500 scale-110 ring-2 ring-primary-500 ring-offset-1"
1941
+ : "border-default-700", "\n\t\t\t"), style: { backgroundColor: colorValue }, title: colorName, "aria-label": colorName }, colorValue)); };
1942
+ return (jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 ".concat(className), children: [label && (jsxRuntime.jsxs("label", { htmlFor: inputId, className: "block text-sm font-medium text-foreground", children: [label, required && jsxRuntime.jsx("span", { className: "text-danger ml-1", children: "*" })] })), jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [jsxRuntime.jsx("input", { type: "color", id: inputId, name: name, value: "#".concat(stripHash(textValue)), onChange: handleColorPickerChange, disabled: disabled, className: "\n\t\t\t\t\t\t\tw-10 h-10 rounded-lg cursor-pointer border-2 flex-shrink-0\n\t\t\t\t\t\t\ttransition-colors appearance-none bg-transparent p-0.5\n\t\t\t\t\t\t\tfocus:border-primary-500\n\t\t\t\t\t\t\t".concat(disabled ? "opacity-50 cursor-not-allowed" : "hover:border-default-400", "\n\t\t\t\t\t\t\t").concat(error
1943
+ ? "border-danger dark:border-danger-400"
1944
+ : "border-default-300 dark:border-default-700", "\n\t\t\t\t\t\t"), "aria-label": t.customColorLabel, title: t.customColorLabel }), jsxRuntime.jsx(react.Input, { type: "text", value: textValue, onValueChange: handleTextChange, onBlur: handleTextBlur, placeholder: t.placeholder, disabled: disabled, isInvalid: error || isInvalidFormat, size: "sm", variant: "bordered", classNames: {
1945
+ input: "uppercase font-mono text-small",
1946
+ inputWrapper: "min-h-8 h-8 focus-within:!border-primary-500",
1947
+ }, startContent: textValue.startsWith("#") ? null : (jsxRuntime.jsx("span", { className: "text-default-400 text-sm", children: "#" })) })] }), (error || isInvalidFormat) && (jsxRuntime.jsx("p", { className: "text-tiny text-danger", children: isInvalidFormat ? t.invalidColorFormat : errorText }))] }), showPredefinedColors && predefinedColors.length > 0 && (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("p", { className: "text-xs font-medium text-default-600 mb-2", children: t.predefinedColorsLabel }), jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: predefinedColors.map(function (color) {
1948
+ return renderColorCircle(color.value, color.name, normalizeHexColor(value) === normalizeHexColor(color.value));
1949
+ }) })] })), enableRecentColors && recentColors.length > 0 && (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("p", { className: "text-xs font-medium text-default-600 mb-2", children: t.recentColorsLabel }), jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: recentColors.map(function (color) {
1950
+ return renderColorCircle(color, color, normalizeHexColor(value) === color);
1951
+ }) })] }))] }));
1952
+ });
1953
+ ColorPicker.displayName = "ColorPicker";
1954
+
1955
+ var ThemeContext = React.createContext({
1956
+ mode: "light",
1957
+ color: "blue",
1958
+ customHex: null,
1959
+ // biome-ignore lint/suspicious/noEmptyBlockStatements: <explanation>
1960
+ setMode: function () { },
1961
+ // biome-ignore lint/suspicious/noEmptyBlockStatements: <explanation>
1962
+ setColor: function () { },
1963
+ });
1964
+ var useThemeContext = function () {
1965
+ var context = React.useContext(ThemeContext);
1966
+ if (!context) {
1967
+ throw new Error("useThemeContext debe ser usado dentro de un ThemeProvider");
1968
+ }
1969
+ return context;
1970
+ };
1971
+
1854
1972
  /**
1855
1973
  * @file This file contains the theme configurations for the application.
1856
1974
  */
@@ -3535,6 +3653,277 @@ var LindaIcon = function (_a) {
3535
3653
  return (jsxRuntime.jsx("svg", __assign({ xmlns: "http://www.w3.org/2000/svg", width: size, height: size, viewBox: "0 0 24 24", className: className, role: "img", "aria-hidden": "true" }, nativeProps, { children: jsxRuntime.jsxs("g", { fill: "currentColor", children: [jsxRuntime.jsx("path", { d: "M3.84453 3.84453C2.71849 4.97056 2.71849 6.79623 3.84453 7.92226L5.43227 9.51C5.44419 9.49622 5.45669 9.48276 5.46978 9.46967L9.46978 5.46967C9.48284 5.45662 9.49625 5.44415 9.50999 5.43226L7.92226 3.84453C6.79623 2.71849 4.97056 2.71849 3.84453 3.84453Z" }), jsxRuntime.jsx("path", { d: "M10.5679 6.49012C10.556 6.50386 10.5435 6.51728 10.5304 6.53033L6.53044 10.5303C6.51735 10.5434 6.5039 10.5559 6.49011 10.5678L16.0777 20.1555C17.2038 21.2815 19.0294 21.2815 20.1555 20.1555C21.2815 19.0294 21.2815 17.2038 20.1555 16.0777L10.5679 6.49012Z" }), jsxRuntime.jsx("path", { d: "M16.1 2.30719C16.261 1.8976 16.8385 1.8976 16.9994 2.30719L17.4298 3.40247C17.479 3.52752 17.5776 3.62651 17.7022 3.67583L18.7934 4.1078C19.2015 4.26934 19.2015 4.849 18.7934 5.01054L17.7022 5.44252C17.5776 5.49184 17.479 5.59082 17.4298 5.71587L16.9995 6.81115C16.8385 7.22074 16.261 7.22074 16.1 6.81116L15.6697 5.71587C15.6205 5.59082 15.5219 5.49184 15.3973 5.44252L14.3061 5.01054C13.898 4.849 13.898 4.26934 14.3061 4.1078L15.3973 3.67583C15.5219 3.62651 15.6205 3.52752 15.6697 3.40247L16.1 2.30719Z" }), jsxRuntime.jsx("path", { d: "M19.9672 9.12945C20.1281 8.71987 20.7057 8.71987 20.8666 9.12945L21.0235 9.5288C21.0727 9.65385 21.1713 9.75284 21.2959 9.80215L21.6937 9.95965C22.1018 10.1212 22.1018 10.7009 21.6937 10.8624L21.2959 11.0199C21.1713 11.0692 21.0727 11.1682 21.0235 11.2932L20.8666 11.6926C20.7057 12.1022 20.1281 12.1022 19.9672 11.6926L19.8103 11.2932C19.7611 11.1682 19.6625 11.0692 19.5379 11.0199L19.14 10.8624C18.732 10.7009 18.732 10.1212 19.14 9.95965L19.5379 9.80215C19.6625 9.75284 19.7611 9.65385 19.8103 9.5288L19.9672 9.12945Z" }), jsxRuntime.jsx("path", { d: "M5.1332 15.3072C5.29414 14.8976 5.87167 14.8976 6.03261 15.3072L6.18953 15.7065C6.23867 15.8316 6.33729 15.9306 6.46188 15.9799L6.85975 16.1374C7.26783 16.2989 7.26783 16.8786 6.85975 17.0401L6.46188 17.1976C6.33729 17.2469 6.23867 17.3459 6.18953 17.471L6.03261 17.8703C5.87167 18.2799 5.29414 18.2799 5.1332 17.8703L4.97628 17.471C4.92714 17.3459 4.82852 17.2469 4.70393 17.1976L4.30606 17.0401C3.89798 16.8786 3.89798 16.2989 4.30606 16.1374L4.70393 15.9799C4.82852 15.9306 4.92714 15.8316 4.97628 15.7065L5.1332 15.3072Z" })] }) })));
3536
3654
  };
3537
3655
 
3656
+ var LINDA_MASCOT_STATES = [
3657
+ "idle",
3658
+ "processing",
3659
+ "working",
3660
+ "listening",
3661
+ "talking",
3662
+ "ready",
3663
+ ];
3664
+ /** px de cada talla con nombre. Cada una cae en su propio nivel de detalle. */
3665
+ var LINDA_MASCOT_SIZE_PX = {
3666
+ xs: 20,
3667
+ sm: 32,
3668
+ md: 72,
3669
+ lg: 144,
3670
+ };
3671
+ /** Variable CSS que lleva la intensidad de voz (0–1). Parte del contrato público. */
3672
+ var LINDA_MASCOT_LEVEL_VAR = "--linda-mascot-level";
3673
+ /** id de la `<style>` que el componente deja en `<head>`. */
3674
+ var LINDA_MASCOT_STYLE_ID = "aurora-linda-mascot-styles";
3675
+ /** Paleta de la hoja de marca. */
3676
+ var LINDA_MASCOT_PALETTE = {
3677
+ coreLight: "#2A2D4A",
3678
+ coreDark: "#0B0C18",
3679
+ eye: "#EAF2FF",
3680
+ eyeGlow: "#8FB8FF",
3681
+ pink: "#FF8AD8",
3682
+ violet: "#A48BFF",
3683
+ cyan: "#6FE3FF",
3684
+ amber: "#FFD08A",
3685
+ };
3686
+ var resolveMascotPx = function (size) {
3687
+ var _a;
3688
+ if (typeof size === "number") {
3689
+ return Number.isFinite(size) && size > 0 ? size : LINDA_MASCOT_SIZE_PX.md;
3690
+ }
3691
+ return (_a = LINDA_MASCOT_SIZE_PX[size !== null && size !== void 0 ? size : "md"]) !== null && _a !== void 0 ? _a : LINDA_MASCOT_SIZE_PX.md;
3692
+ };
3693
+ /** ≤20 xs · 21–40 sm · 41–95 md · ≥96 lg. */
3694
+ var resolveMascotTier = function (px) {
3695
+ if (px <= 20) {
3696
+ return "xs";
3697
+ }
3698
+ if (px <= 40) {
3699
+ return "sm";
3700
+ }
3701
+ if (px < 96) {
3702
+ return "md";
3703
+ }
3704
+ return "lg";
3705
+ };
3706
+ var clampLevel = function (level) {
3707
+ if (typeof level !== "number" || Number.isNaN(level)) {
3708
+ return 0;
3709
+ }
3710
+ return Math.min(1, Math.max(0, level));
3711
+ };
3712
+ var LINDA_MASCOT_GEOMETRY = {
3713
+ xs: {
3714
+ coreRx: 40,
3715
+ coreCy: 61,
3716
+ eyeWidth: 17,
3717
+ eyeHeight: 8,
3718
+ eyeStroke: 9,
3719
+ eyeGap: 31,
3720
+ rings: [{ r: 57, squash: 0.3, tilt: -16, strokePx: 1.2, opacity: 0.95 }],
3721
+ halo: false,
3722
+ specular: false,
3723
+ blur: false,
3724
+ ringGlow: "none",
3725
+ },
3726
+ sm: {
3727
+ coreRx: 36,
3728
+ coreCy: 61,
3729
+ eyeWidth: 14,
3730
+ eyeHeight: 6.5,
3731
+ eyeStroke: 6,
3732
+ eyeGap: 28,
3733
+ rings: [
3734
+ { r: 56, squash: 0.3, tilt: -16, strokePx: 1.1, opacity: 0.9 },
3735
+ { r: 52, squash: 0.36, tilt: 20, strokePx: 1, opacity: 0.7 },
3736
+ ],
3737
+ halo: true,
3738
+ specular: false,
3739
+ blur: false,
3740
+ ringGlow: "none",
3741
+ },
3742
+ md: {
3743
+ coreRx: 33,
3744
+ coreCy: 61,
3745
+ eyeWidth: 12.5,
3746
+ eyeHeight: 5.5,
3747
+ eyeStroke: 4.4,
3748
+ eyeGap: 25,
3749
+ rings: [
3750
+ { r: 56, squash: 0.3, tilt: -16, strokePx: 1.5, opacity: 0.85 },
3751
+ { r: 52, squash: 0.38, tilt: 20, strokePx: 1.2, opacity: 0.7 },
3752
+ { r: 58, squash: 0.2, tilt: -3, strokePx: 1, opacity: 0.55 },
3753
+ ],
3754
+ halo: true,
3755
+ specular: true,
3756
+ blur: true,
3757
+ ringGlow: "flat",
3758
+ },
3759
+ lg: {
3760
+ coreRx: 32,
3761
+ coreCy: 61,
3762
+ eyeWidth: 12,
3763
+ eyeHeight: 5.2,
3764
+ eyeStroke: 3.8,
3765
+ eyeGap: 24,
3766
+ rings: [
3767
+ { r: 56, squash: 0.3, tilt: -16, strokePx: 2, opacity: 0.85 },
3768
+ { r: 52, squash: 0.38, tilt: 20, strokePx: 1.6, opacity: 0.72 },
3769
+ { r: 58, squash: 0.2, tilt: -3, strokePx: 1.3, opacity: 0.58 },
3770
+ ],
3771
+ halo: true,
3772
+ specular: true,
3773
+ blur: true,
3774
+ ringGlow: "blur",
3775
+ },
3776
+ };
3777
+
3778
+ var LEVEL = "var(".concat(LINDA_MASCOT_LEVEL_VAR, ")");
3779
+ var AUTO_THEME = themeScopeSelectors('.aurora-linda-mascot[data-appearance="auto"]');
3780
+ /** Curva de los movimientos que responden a la voz: sale rápido, llega suave. */
3781
+ var EASE_OUT = "cubic-bezier(0.22, 0.7, 0.3, 1)";
3782
+ /**
3783
+ * Reglas de la mascota. Viajan con el componente (se inyectan en `<head>`, ver
3784
+ * `useInjectedStyle`) para que funcione en un microfrontend que no carga `styles.css`.
3785
+ *
3786
+ * Todo se anima con `transform` u `opacity`. Cada grupo animado es un `<g>` SIN atributo
3787
+ * `transform`: en SVG la propiedad CSS `transform` reemplaza al atributo, así que la
3788
+ * geometría (posición, inclinación, aplastamiento) vive en grupos padres y el movimiento
3789
+ * en grupos hijos. Por la misma razón, lo que sigue a la voz (`--linda-mascot-level`,
3790
+ * con `transition`) y lo que late en bucle (con `animation`) van en grupos distintos: una
3791
+ * animación CSS anula la transición de la misma propiedad.
3792
+ */
3793
+ /** Reglas de movimiento reducido bajo la raíz \`root\` (clase o clase+atributo). */
3794
+ var reducedMotionBody = function (root) { return "\n\t".concat(root, " .aurora-lm-spin,\n\t").concat(root, " .aurora-lm-boost,\n\t").concat(root, " .aurora-lm-orbit,\n\t").concat(root, " .aurora-lm-eyes,\n\t").concat(root, " .aurora-lm-breathe,\n\t").concat(root, " .aurora-lm-halo,\n\t").concat(root, " .aurora-lm-sparkle {\n\t\tanimation: none !important;\n\t}\n\t").concat(root, " .aurora-lm-level-body,\n\t").concat(root, " .aurora-lm-level-rings,\n\t").concat(root, " .aurora-lm-level-halo {\n\t\ttransform: none !important;\n\t}\n\t").concat(root, ".aurora-linda-mascot--listening .aurora-lm-level-rings,\n\t").concat(root, ".aurora-linda-mascot--talking .aurora-lm-level-rings {\n\t\topacity: calc(0.55 + ").concat(LEVEL, " * 0.45);\n\t}\n\t").concat(root, ".aurora-linda-mascot--processing .aurora-lm-halo {\n\t\tanimation: aurora-lm-glow 1.6s ease-in-out infinite !important;\n\t}\n\t").concat(root, ".aurora-linda-mascot--working .aurora-lm-halo {\n\t\topacity: 1 !important;\n\t}\n\t").concat(root, ".aurora-linda-mascot--listening .aurora-lm-level-halo,\n\t").concat(root, ".aurora-linda-mascot--talking .aurora-lm-level-halo {\n\t\topacity: calc(0.4 + ").concat(LEVEL, " * 0.6) !important;\n\t}\n\t").concat(root, ".aurora-linda-mascot--ready .aurora-lm-sparkle {\n\t\tanimation: aurora-lm-sparkle-fade 700ms ease-out 1 both !important;\n\t}\n"); };
3795
+ var reducedMotionRules = function (root) { return "\n@media (prefers-reduced-motion: reduce) {".concat(reducedMotionBody(root), "}\n").concat(reducedMotionBody("".concat(root, "[data-motion=\"reduce\"]")), "\n"); };
3796
+ var LINDA_MASCOT_CSS = "\n.aurora-linda-mascot {\n\t".concat(LINDA_MASCOT_LEVEL_VAR, ": 0;\n\t--lm-halo: 0.5;\n\t--lm-shadow: 1;\n\t--lm-rim: 0.85;\n\t--lm-sparkle: #F2B441;\n\tdisplay: inline-block;\n\tflex-shrink: 0;\n\toverflow: visible;\n\tvertical-align: middle;\n}\n/* En lg la mascota es escenario (bienvenida, llamada): m\u00E1s halo, como en la hoja de marca.\n Multiplicador aparte para no competir en especificidad con las reglas de tema. */\n.aurora-linda-mascot--tier-lg {\n\t--lm-halo-boost: 1.4;\n}\n/*\n * Tema. `auto` sigue al ancestro claro/oscuro m\u00E1s cercano, incluidos los temas de aurora\n * (`blue-dark`\u2026); ver `themeScopeSelectors`.\n */\n").concat(AUTO_THEME.dark, ",\n.aurora-linda-mascot[data-appearance=\"dark\"] {\n\t--lm-halo: 0.95;\n\t--lm-shadow: 0;\n\t--lm-rim: 1;\n\t--lm-sparkle: #FFF1C9;\n}\n").concat(AUTO_THEME.light, " {\n\t--lm-halo: 0.5;\n\t--lm-shadow: 1;\n\t--lm-rim: 0.85;\n\t--lm-sparkle: #F2B441;\n}\n\n/* Cuerpo entero: respiraci\u00F3n en bucle + escala por voz (grupos distintos). */\n.aurora-lm-breathe,\n.aurora-lm-level-body,\n.aurora-lm-level-rings {\n\ttransform-box: view-box;\n\ttransform-origin: 60px 61px;\n}\n.aurora-lm-breathe {\n\tanimation: aurora-lm-breathe 2s ease-in-out infinite alternate;\n}\n.aurora-lm-level-body,\n.aurora-lm-level-rings,\n.aurora-lm-level-halo {\n\ttransition: transform 140ms ").concat(EASE_OUT, ", opacity 240ms ").concat(EASE_OUT, ";\n}\n\n/* Halo y sombra de contacto. */\n.aurora-lm-halo,\n.aurora-lm-level-halo {\n\ttransform-box: fill-box;\n\ttransform-origin: center;\n}\n.aurora-lm-halo {\n\topacity: calc(var(--lm-halo) * var(--lm-halo-boost, 1));\n\ttransition: opacity 400ms ease;\n}\n.aurora-lm-shadow {\n\topacity: var(--lm-shadow);\n}\n.aurora-lm-rim {\n\topacity: var(--lm-rim);\n}\n\n/*\n * Anillos. El c\u00EDrculo gira dentro de su grupo aplastado: la elipse no cambia de forma y\n * lo que recorre el trazo es el color, como un anillo que gira en profundidad.\n * `--lm-spin-duration` y `--lm-spin-direction` llegan por anillo desde el marcado.\n */\n.aurora-lm-spin {\n\ttransform-box: view-box;\n\ttransform-origin: 0 0;\n\tanimation: aurora-lm-spin var(--lm-spin-duration, 24s) linear infinite\n\t\tvar(--lm-spin-direction, normal);\n}\n/* Segundo giro encadenado: parado salvo en working, donde dobla la velocidad sin saltos\n (pausar conserva el \u00E1ngulo; cambiar la duraci\u00F3n lo har\u00EDa saltar). */\n.aurora-lm-boost {\n\tanimation-play-state: paused;\n}\n/* Cometa del anillo principal: orbita siempre, se ve solo al pensar o trabajar. */\n.aurora-lm-orbit {\n\tanimation-play-state: paused;\n}\n.aurora-lm-comet,\n.aurora-lm-glint {\n\topacity: 0;\n\ttransition: opacity 320ms ease;\n}\n\n/* Ojos: solo parpadean (sin expresiones faciales). Dos parpadeos por ciclo, a 4,8 y 6,2 s. */\n.aurora-lm-eyes {\n\ttransform-box: fill-box;\n\ttransform-origin: center;\n\tanimation: aurora-lm-blink 11s ease-in-out infinite;\n}\n\n/* Chispas de fin de turno. */\n/* Dorado en claro (el blanco desaparece sobre fondo claro), casi blanco en oscuro. */\n.aurora-lm-sparkle {\n\ttransform-box: fill-box;\n\ttransform-origin: center;\n\topacity: 0;\n\tfill: var(--lm-sparkle);\n}\n\n/* \u2500\u2500 Estados \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n/* idle no a\u00F1ade nada: es el movimiento base de arriba (giro, respiraci\u00F3n, parpadeo). */\n\n.aurora-linda-mascot--processing .aurora-lm-orbit {\n\tanimation-play-state: running;\n}\n.aurora-linda-mascot--processing .aurora-lm-comet {\n\topacity: 1;\n}\n.aurora-linda-mascot--processing .aurora-lm-halo {\n\tanimation: aurora-lm-pulse 1.6s ease-in-out infinite;\n}\n\n.aurora-linda-mascot--working .aurora-lm-boost,\n.aurora-linda-mascot--working .aurora-lm-orbit {\n\tanimation-play-state: running;\n}\n.aurora-linda-mascot--working .aurora-lm-glint {\n\topacity: 1;\n}\n\n.aurora-linda-mascot--listening .aurora-lm-level-rings {\n\ttransform: scale(calc(0.86 + ").concat(LEVEL, " * 0.16));\n}\n.aurora-linda-mascot--listening .aurora-lm-level-halo {\n\ttransform: scale(calc(0.92 + ").concat(LEVEL, " * 0.2));\n}\n\n.aurora-linda-mascot--talking .aurora-lm-level-body {\n\ttransform: scale(calc(1 + ").concat(LEVEL, " * 0.07));\n}\n.aurora-linda-mascot--talking .aurora-lm-level-halo {\n\ttransform: scale(calc(1 + ").concat(LEVEL, " * 0.32));\n\topacity: calc(0.75 + ").concat(LEVEL, " * 0.25);\n}\n\n.aurora-linda-mascot--ready .aurora-lm-sparkle {\n\tanimation: aurora-lm-sparkle 700ms cubic-bezier(0.2, 0.8, 0.3, 1) 1 both;\n\tanimation-delay: var(--lm-sparkle-delay, 0ms);\n}\n\n/* \u2500\u2500 Keyframes \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n@keyframes aurora-lm-spin {\n\tto {\n\t\ttransform: rotate(360deg);\n\t}\n}\n@keyframes aurora-lm-breathe {\n\tfrom {\n\t\ttransform: scale(1);\n\t}\n\tto {\n\t\ttransform: scale(1.03);\n\t}\n}\n@keyframes aurora-lm-blink {\n\t0%, 42%, 45%, 97.5%, 100% {\n\t\ttransform: scaleY(1);\n\t}\n\t43.5%, 98.8% {\n\t\ttransform: scaleY(0.12);\n\t}\n}\n@keyframes aurora-lm-pulse {\n\t0%, 100% {\n\t\ttransform: scale(1);\n\t\topacity: calc(var(--lm-halo) * var(--lm-halo-boost, 1));\n\t}\n\t50% {\n\t\ttransform: scale(1.12);\n\t\topacity: 1;\n\t}\n}\n@keyframes aurora-lm-glow {\n\t0%, 100% {\n\t\topacity: calc(var(--lm-halo) * var(--lm-halo-boost, 1));\n\t}\n\t50% {\n\t\topacity: 1;\n\t}\n}\n@keyframes aurora-lm-sparkle {\n\t0% {\n\t\topacity: 0;\n\t\ttransform: scale(0.2) rotate(0deg);\n\t}\n\t35% {\n\t\topacity: 1;\n\t\ttransform: scale(1) rotate(45deg);\n\t}\n\t100% {\n\t\topacity: 0;\n\t\ttransform: scale(0.5) rotate(90deg);\n\t}\n}\n@keyframes aurora-lm-sparkle-fade {\n\t0%, 100% {\n\t\topacity: 0;\n\t}\n\t35% {\n\t\topacity: 1;\n\t}\n}\n\n/*\n * Movimiento reducido: nada gira, parpadea, respira ni crece. El estado se sigue leyendo\n * sin movimiento: al pensar o trabajar el cometa o el destello se quedan quietos sobre el\n * anillo (as\u00ED se distingue tambi\u00E9n en `xs`, que no tiene halo) y el halo late en opacidad\n * o se enciende; con la voz sube la opacidad del halo y de los anillos; las chispas\n * aparecen y se desvanecen sin moverse.\n *\n * Las mismas reglas se aplican con la preferencia del sistema y con `motion=\"reduce\"`\n * (`data-motion`), que el consumidor usa para listas largas o para forzarlo. `!important`\n * porque las reglas por estado de arriba tienen m\u00E1s especificidad y `@media` no la sube.\n */\n").concat(reducedMotionRules(".aurora-linda-mascot"), "\n");
3797
+
3798
+ var CX = 60;
3799
+ var STYLE_ID = styleIdFor(LINDA_MASCOT_STYLE_ID, LINDA_MASCOT_CSS);
3800
+ /** Velocidad de giro por anillo (s por vuelta) y sentido. */
3801
+ var RING_MOTION = [
3802
+ { duration: "24s", direction: "normal" },
3803
+ { duration: "30s", direction: "reverse" },
3804
+ { duration: "36s", direction: "normal" },
3805
+ ];
3806
+ /** Chispas de `ready`: posición en el viewBox, tamaño y retardo. */
3807
+ var SPARKLES = [
3808
+ { x: 90, y: 17, s: 9, delay: "0ms" },
3809
+ { x: 104, y: 35, s: 5.5, delay: "90ms" },
3810
+ { x: 73, y: 7, s: 4.5, delay: "170ms" },
3811
+ ];
3812
+ var sparklePath = function (s) {
3813
+ var k = s * 0.18;
3814
+ return "M0 ".concat(-s, "C").concat(k, " ").concat(-k, " ").concat(k, " ").concat(-k, " ").concat(s, " 0C").concat(k, " ").concat(k, " ").concat(k, " ").concat(k, " 0 ").concat(s, "C").concat(-k, " ").concat(k, " ").concat(-k, " ").concat(k, " ").concat(-s, " 0C").concat(-k, " ").concat(-k, " ").concat(-k, " ").concat(-k, " 0 ").concat(-s, "Z");
3815
+ };
3816
+ /**
3817
+ * Perímetro en px de pantalla de la elipse de un anillo. Con `non-scaling-stroke` los
3818
+ * guiones se miden en px de pantalla (no en unidades del viewBox ni en `pathLength`), así
3819
+ * que el cometa se dimensiona como fracción de este perímetro para medir lo mismo a
3820
+ * cualquier talla.
3821
+ */
3822
+ var ringPerimeterPx = function (ring, px) {
3823
+ var a = (ring.r * px) / 120;
3824
+ var b = a * ring.squash;
3825
+ var h = Math.pow(((a - b) / (a + b)), 2);
3826
+ return Math.PI * (a + b) * (1 + (3 * h) / (10 + Math.sqrt(4 - 3 * h)));
3827
+ };
3828
+ /**
3829
+ * Cometa con estela sobre un anillo: cola de `steps` tramos consecutivos con el
3830
+ * iridiscente del anillo, cada uno más opaco y más grueso que el anterior, y una cabeza
3831
+ * redonda y brillante al final. Todo es `stroke-dasharray` sobre el mismo círculo que el
3832
+ * anillo, así que gira con `transform` y se recorta delante/detrás igual que él. El giro
3833
+ * es horario: la cabeza va al final del trazo, por delante de su cola.
3834
+ */
3835
+ var Comet = function (_a) {
3836
+ var className = _a.className, r = _a.r, perimeter = _a.perimeter, tail = _a.tail, strokePx = _a.strokePx, headPx = _a.headPx, steps = _a.steps, ringPaint = _a.ringPaint, headPaint = _a.headPaint;
3837
+ var tailPx = perimeter * tail;
3838
+ var seg = tailPx / steps;
3839
+ return (jsxRuntime.jsxs("g", { className: className, "data-part": "comet", children: [Array.from({ length: steps }, function (_, i) {
3840
+ var t = (i + 1) / steps;
3841
+ return (jsxRuntime.jsx("circle", { r: r, fill: "none", stroke: ringPaint, strokeWidth: strokePx * (0.8 + 1.6 * t), strokeOpacity: Math.pow(t, 1.5), strokeDasharray: "".concat((seg + 0.4).toFixed(2), " ").concat((perimeter - seg - 0.4).toFixed(2)), strokeDashoffset: (-seg * i).toFixed(2), vectorEffect: "non-scaling-stroke" }, i));
3842
+ }), jsxRuntime.jsx("circle", { r: r, fill: "none", stroke: headPaint, strokeWidth: headPx * 1.5, strokeOpacity: 0.3, strokeLinecap: "round", strokeDasharray: "0.01 ".concat((perimeter - 0.01).toFixed(2)), strokeDashoffset: (-tailPx).toFixed(2), vectorEffect: "non-scaling-stroke" }), jsxRuntime.jsx("circle", { r: r, fill: "none", stroke: "#FFFFFF", strokeWidth: headPx, strokeLinecap: "round", strokeDasharray: "0.01 ".concat((perimeter - 0.01).toFixed(2)), strokeDashoffset: (-tailPx).toFixed(2), vectorEffect: "non-scaling-stroke" })] }));
3843
+ };
3844
+ /** Arco «∩» de un ojo centrado en (x, y): ancho w, alto h. */
3845
+ var eyePath = function (x, y, w, h) {
3846
+ var half = w / 2;
3847
+ var base = y + h / 2;
3848
+ var control = y - h * 0.8333;
3849
+ return "M".concat(x - half, " ").concat(base, "C").concat(x - half, " ").concat(control, " ").concat(x + half, " ").concat(control, " ").concat(x + half, " ").concat(base);
3850
+ };
3851
+ /**
3852
+ * `useId` devuelve `:r0:` (React 18), `«r0»` o `_r_0_` (19): fuera lo que no vale en un
3853
+ * id referenciado desde `url(#…)`.
3854
+ */
3855
+ var safeId = function (raw) {
3856
+ return "lm".concat(raw.replace(/[^a-zA-Z0-9_-]/g, ""));
3857
+ };
3858
+ /**
3859
+ * LindaMascot — la cara de Linda: un orbe de tinta con ojos luminosos y anillos
3860
+ * iridiscentes, en SVG + CSS (sin imágenes, fuentes ni WebGL).
3861
+ *
3862
+ * Se anima según lo que Linda está haciendo (`state`) y, en la llamada de voz, según el
3863
+ * volumen (`level`), sin preguntar nada al modelo. Pinta más o menos detalle según la
3864
+ * talla para leerse igual a 16 px que a 200 px. Ver README.
3865
+ */
3866
+ var LindaMascot = React.forwardRef(function LindaMascot(_a, ref) {
3867
+ var _b;
3868
+ var _c = _a.state, state = _c === void 0 ? "idle" : _c, _d = _a.size, size = _d === void 0 ? "md" : _d, level = _a.level, label = _a.label, _e = _a.appearance, appearance = _e === void 0 ? "auto" : _e, _f = _a.motion, motion = _f === void 0 ? "auto" : _f, className = _a.className, style = _a.style, svgProps = __rest(_a, ["state", "size", "level", "label", "appearance", "motion", "className", "style"]);
3869
+ useInjectedStyle(STYLE_ID, LINDA_MASCOT_CSS);
3870
+ var uid = safeId(React.useId());
3871
+ var px = resolveMascotPx(size);
3872
+ var tier = resolveMascotTier(px);
3873
+ var g = LINDA_MASCOT_GEOMETRY[tier];
3874
+ var coreRy = g.coreRx * 0.92;
3875
+ var eyeY = g.coreCy - coreRy + coreRy * 2 * 0.45;
3876
+ var eyes = [CX - g.eyeGap / 2, CX + g.eyeGap / 2];
3877
+ // Recorte delante/detrás: en lg los velos desenfocados salen más allá del anillo.
3878
+ var clipHalf = g.ringGlow === "blur" ? 120 : 80;
3879
+ var id = {
3880
+ core: "".concat(uid, "-core"),
3881
+ coreClip: "".concat(uid, "-core-clip"),
3882
+ rim: "".concat(uid, "-rim"),
3883
+ ring: "".concat(uid, "-ring"),
3884
+ halo: "".concat(uid, "-halo"),
3885
+ shadow: "".concat(uid, "-shadow"),
3886
+ specular: "".concat(uid, "-specular"),
3887
+ back: "".concat(uid, "-back"),
3888
+ front: "".concat(uid, "-front"),
3889
+ soft: "".concat(uid, "-soft"),
3890
+ eyeGlow: "".concat(uid, "-eye-glow"),
3891
+ aura: "".concat(uid, "-aura"),
3892
+ veil: "".concat(uid, "-veil"),
3893
+ tail: "".concat(uid, "-tail"),
3894
+ };
3895
+ var a11y = label
3896
+ ? { role: "img", "aria-label": label }
3897
+ : { "aria-hidden": true };
3898
+ var renderRing = function (ring, index, half) {
3899
+ var motion = RING_MOTION[index];
3900
+ var spinStyle = {
3901
+ "--lm-spin-duration": motion.duration,
3902
+ "--lm-spin-direction": motion.direction,
3903
+ };
3904
+ var isMain = index === 0;
3905
+ var perimeter = ringPerimeterPx(ring, px);
3906
+ return (jsxRuntime.jsx("g", { "data-ring": index + 1, "data-ring-half": half, transform: "translate(".concat(CX, " ").concat(g.coreCy, ") rotate(").concat(ring.tilt, ")"), opacity: half === "back" ? ring.opacity * 0.62 : ring.opacity, children: jsxRuntime.jsx("g", { clipPath: "url(#".concat(half === "back" ? id.back : id.front, ")"), children: jsxRuntime.jsxs("g", { transform: "scale(1 ".concat(ring.squash, ")"), children: [jsxRuntime.jsx("g", { className: "aurora-lm-spin", style: spinStyle, children: jsxRuntime.jsxs("g", { className: "aurora-lm-spin aurora-lm-boost", style: spinStyle, children: [g.ringGlow === "blur" && (jsxRuntime.jsx("circle", { "data-part": "veil", r: ring.r, fill: "none", stroke: "url(#".concat(id.ring, ")"), strokeWidth: ring.strokePx * 16, strokeOpacity: 0.3, vectorEffect: "non-scaling-stroke", filter: "url(#".concat(id.veil, ")") })), g.ringGlow !== "none" && (jsxRuntime.jsx("circle", { r: ring.r, fill: "none", stroke: "url(#".concat(id.ring, ")"), strokeWidth: ring.strokePx * (g.ringGlow === "blur" ? 6.5 : 5), strokeOpacity: g.ringGlow === "blur" ? 0.34 : 0.14, vectorEffect: "non-scaling-stroke", filter: g.ringGlow === "blur" ? "url(#".concat(id.soft, ")") : undefined })), g.ringGlow !== "none" && (jsxRuntime.jsx("circle", { r: ring.r + 2.2, fill: "none", stroke: "url(#".concat(id.ring, ")"), strokeWidth: ring.strokePx * 0.55, strokeOpacity: 0.55, vectorEffect: "non-scaling-stroke" })), jsxRuntime.jsx("circle", { r: ring.r, fill: "none", stroke: "url(#".concat(id.ring, ")"), strokeWidth: ring.strokePx, vectorEffect: "non-scaling-stroke" })] }) }), isMain && (jsxRuntime.jsxs("g", { className: "aurora-lm-spin aurora-lm-orbit", style: {
3907
+ "--lm-spin-duration": "1.6s",
3908
+ }, children: [jsxRuntime.jsx(Comet, { className: "aurora-lm-comet", r: ring.r, perimeter: perimeter, tail: 0.3, strokePx: ring.strokePx, headPx: Math.max(2, ring.strokePx * 2.4), steps: tier === "xs" ? 6 : 12, ringPaint: "url(#".concat(id.tail, ")"), headPaint: LINDA_MASCOT_PALETTE.eyeGlow }), jsxRuntime.jsx(Comet, { className: "aurora-lm-glint", r: ring.r, perimeter: perimeter, tail: 0.14, strokePx: ring.strokePx * 1.2, headPx: Math.max(2.4, ring.strokePx * 3), steps: tier === "xs" ? 4 : 8, ringPaint: "url(#".concat(id.tail, ")"), headPaint: LINDA_MASCOT_PALETTE.eyeGlow })] }))] }) }) }, "".concat(half, "-").concat(index)));
3909
+ };
3910
+ var ringHalves = function (half) {
3911
+ return g.rings.map(function (ring, index) { return renderRing(ring, index, half); });
3912
+ };
3913
+ return (
3914
+ // biome-ignore lint/a11y/noSvgWithoutTitle: el nombre llega por aria-label (con `label`) o la mascota es decorativa (aria-hidden); biome no ve el spread de `a11y`.
3915
+ jsxRuntime.jsxs("svg", __assign({ ref: ref, xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 120 120", width: px, height: px, focusable: "false", className: [
3916
+ "aurora-linda-mascot",
3917
+ "aurora-linda-mascot--".concat(state),
3918
+ "aurora-linda-mascot--tier-".concat(tier),
3919
+ className,
3920
+ ]
3921
+ .filter(Boolean)
3922
+ .join(" "), "data-state": state, "data-tier": tier, "data-appearance": appearance, "data-motion": motion, style: __assign(__assign({}, style), (_b = {}, _b[LINDA_MASCOT_LEVEL_VAR] = clampLevel(level), _b)) }, a11y, svgProps, { children: [jsxRuntime.jsxs("defs", { children: [jsxRuntime.jsxs("radialGradient", { id: id.core, cx: "0.4", cy: "0.34", r: "0.72", children: [jsxRuntime.jsx("stop", { offset: "0", stopColor: LINDA_MASCOT_PALETTE.coreLight }), jsxRuntime.jsx("stop", { offset: "0.6", stopColor: "#15172B" }), jsxRuntime.jsx("stop", { offset: "1", stopColor: LINDA_MASCOT_PALETTE.coreDark })] }), jsxRuntime.jsxs("linearGradient", { id: id.ring, x1: "0", y1: "0", x2: "1", y2: "1", children: [jsxRuntime.jsx("stop", { offset: "0", stopColor: LINDA_MASCOT_PALETTE.pink }), jsxRuntime.jsx("stop", { offset: "0.36", stopColor: LINDA_MASCOT_PALETTE.violet }), jsxRuntime.jsx("stop", { offset: "0.68", stopColor: LINDA_MASCOT_PALETTE.cyan }), jsxRuntime.jsx("stop", { offset: "1", stopColor: LINDA_MASCOT_PALETTE.amber })] }), jsxRuntime.jsxs("linearGradient", { id: id.tail, x1: "0", y1: "0", x2: "1", y2: "1", children: [jsxRuntime.jsx("stop", { offset: "0", stopColor: "#FFC4EC" }), jsxRuntime.jsx("stop", { offset: "0.36", stopColor: "#D4C8FF" }), jsxRuntime.jsx("stop", { offset: "0.68", stopColor: "#B8F1FF" }), jsxRuntime.jsx("stop", { offset: "1", stopColor: "#FFE6BF" })] }), jsxRuntime.jsxs("linearGradient", { id: id.rim, x1: "0.2", y1: "0", x2: "0.5", y2: "1", children: [jsxRuntime.jsx("stop", { offset: "0", stopColor: LINDA_MASCOT_PALETTE.violet }), jsxRuntime.jsx("stop", { offset: "0.42", stopColor: LINDA_MASCOT_PALETTE.cyan }), jsxRuntime.jsx("stop", { offset: "0.74", stopColor: LINDA_MASCOT_PALETTE.pink }), jsxRuntime.jsx("stop", { offset: "1", stopColor: LINDA_MASCOT_PALETTE.amber })] }), jsxRuntime.jsx("clipPath", { id: id.coreClip, children: jsxRuntime.jsx("ellipse", { cx: CX, cy: g.coreCy, rx: g.coreRx, ry: coreRy }) }), jsxRuntime.jsx("clipPath", { id: id.back, children: jsxRuntime.jsx("rect", { x: -clipHalf, y: -clipHalf, width: clipHalf * 2, height: clipHalf }) }), jsxRuntime.jsx("clipPath", { id: id.front, children: jsxRuntime.jsx("rect", { x: -clipHalf, y: 0, width: clipHalf * 2, height: clipHalf }) }), g.halo && (jsxRuntime.jsxs("radialGradient", { id: id.halo, children: [jsxRuntime.jsx("stop", { offset: "0", stopColor: LINDA_MASCOT_PALETTE.violet, stopOpacity: "0.7" }), jsxRuntime.jsx("stop", { offset: tier === "lg" ? "0.48" : "0.42", stopColor: LINDA_MASCOT_PALETTE.pink, stopOpacity: tier === "lg" ? "0.36" : "0.28" }), jsxRuntime.jsx("stop", { offset: tier === "lg" ? "0.78" : "0.7", stopColor: LINDA_MASCOT_PALETTE.cyan, stopOpacity: tier === "lg" ? "0.14" : "0.08" }), jsxRuntime.jsx("stop", { offset: "1", stopColor: LINDA_MASCOT_PALETTE.cyan, stopOpacity: "0" })] })), g.halo && (jsxRuntime.jsxs("radialGradient", { id: id.shadow, children: [jsxRuntime.jsx("stop", { offset: "0", stopColor: LINDA_MASCOT_PALETTE.coreDark, stopOpacity: "0.28" }), jsxRuntime.jsx("stop", { offset: "1", stopColor: LINDA_MASCOT_PALETTE.coreDark, stopOpacity: "0" })] })), g.specular && (jsxRuntime.jsxs("radialGradient", { id: id.specular, children: [jsxRuntime.jsx("stop", { offset: "0", stopColor: "#FFFFFF", stopOpacity: "0.2" }), jsxRuntime.jsx("stop", { offset: "1", stopColor: "#FFFFFF", stopOpacity: "0" })] })), g.blur && (jsxRuntime.jsx("filter", { id: id.eyeGlow, filterUnits: "userSpaceOnUse", x: "-20", y: "-20", width: "160", height: "160", children: jsxRuntime.jsx("feGaussianBlur", { stdDeviation: "2.2" }) })), g.blur && (jsxRuntime.jsx("filter", { id: id.aura, filterUnits: "userSpaceOnUse", x: "-20", y: "-20", width: "160", height: "160", children: jsxRuntime.jsx("feGaussianBlur", { stdDeviation: tier === "lg" ? 5.5 : 4 }) })), g.ringGlow === "blur" && (jsxRuntime.jsx("filter", { id: id.soft, filterUnits: "userSpaceOnUse", x: "-90", y: "-90", width: "180", height: "180", children: jsxRuntime.jsx("feGaussianBlur", { stdDeviation: "2.6" }) })), g.ringGlow === "blur" && (jsxRuntime.jsx("filter", { id: id.veil, filterUnits: "userSpaceOnUse", x: "-100", y: "-100", width: "200", height: "200", children: jsxRuntime.jsx("feGaussianBlur", { stdDeviation: "5" }) }))] }), jsxRuntime.jsx("g", { className: "aurora-lm-level-body", children: jsxRuntime.jsxs("g", { className: "aurora-lm-breathe", children: [g.halo && (jsxRuntime.jsx("g", { className: "aurora-lm-level-halo", children: jsxRuntime.jsx("circle", { className: "aurora-lm-halo", "data-part": "halo", cx: CX, cy: g.coreCy, r: tier === "lg" ? 61 : 58, fill: "url(#".concat(id.halo, ")") }) })), g.halo && (jsxRuntime.jsx("ellipse", { className: "aurora-lm-shadow", "data-part": "shadow", cx: CX, cy: g.coreCy + coreRy + 9, rx: g.coreRx * 0.8, ry: 4.5, fill: "url(#".concat(id.shadow, ")") })), jsxRuntime.jsx("g", { className: "aurora-lm-rings aurora-lm-level-rings", children: ringHalves("back") }), tier !== "xs" && (jsxRuntime.jsx("ellipse", { className: "aurora-lm-rim", "data-part": "aura", cx: CX, cy: g.coreCy, rx: g.coreRx + 1, ry: coreRy + 1, fill: "none", stroke: "url(#".concat(id.rim, ")"), strokeWidth: tier === "lg" ? 9 : g.blur ? 7 : 3, strokeOpacity: tier === "lg" ? 0.85 : g.blur ? 0.75 : 0.45, filter: g.blur ? "url(#".concat(id.aura, ")") : undefined })), jsxRuntime.jsxs("g", { "data-part": "core", children: [jsxRuntime.jsx("ellipse", { cx: CX, cy: g.coreCy, rx: g.coreRx, ry: coreRy, fill: "url(#".concat(id.core, ")") }), jsxRuntime.jsx("g", { clipPath: "url(#".concat(id.coreClip, ")"), children: jsxRuntime.jsx("ellipse", { className: "aurora-lm-rim", cx: CX, cy: g.coreCy, rx: g.coreRx, ry: coreRy, fill: "none", stroke: "url(#".concat(id.rim, ")"), strokeWidth: tier === "xs" ? 5 : g.blur ? 7 : 5, filter: g.blur ? "url(#".concat(id.eyeGlow, ")") : undefined }) }), g.specular && (jsxRuntime.jsx("ellipse", { "data-part": "specular", cx: CX - g.coreRx * 0.36, cy: g.coreCy - coreRy * 0.5, rx: g.coreRx * 0.38, ry: g.coreRx * 0.2, transform: "rotate(-28 ".concat(CX - g.coreRx * 0.36, " ").concat(g.coreCy - coreRy * 0.5, ")"), fill: "url(#".concat(id.specular, ")") }))] }), jsxRuntime.jsxs("g", { className: "aurora-lm-eyes", "data-part": "eyes", children: [eyes.map(function (x) { return (jsxRuntime.jsx("path", { d: eyePath(x, eyeY, g.eyeWidth, g.eyeHeight), fill: "none", stroke: LINDA_MASCOT_PALETTE.eyeGlow, strokeWidth: g.eyeStroke * (g.blur ? 2.2 : 1.7), strokeLinecap: "round", strokeOpacity: g.blur ? 0.85 : 0.35, filter: g.blur ? "url(#".concat(id.eyeGlow, ")") : undefined }, "glow-".concat(x))); }), eyes.map(function (x) { return (jsxRuntime.jsx("path", { "data-part": "eye", d: eyePath(x, eyeY, g.eyeWidth, g.eyeHeight), fill: "none", stroke: LINDA_MASCOT_PALETTE.eye, strokeWidth: g.eyeStroke, strokeLinecap: "round" }, "eye-".concat(x))); })] }), jsxRuntime.jsx("g", { className: "aurora-lm-rings aurora-lm-level-rings", children: ringHalves("front") }), state === "ready" && tier !== "xs" && (jsxRuntime.jsx("g", { "data-part": "sparkles", children: SPARKLES.map(function (s) { return (jsxRuntime.jsx("g", { transform: "translate(".concat(s.x, " ").concat(s.y, ")"), children: jsxRuntime.jsx("path", { className: "aurora-lm-sparkle", d: sparklePath(s.s), style: {
3923
+ "--lm-sparkle-delay": s.delay,
3924
+ } }) }, "".concat(s.x, "-").concat(s.y))); }) }))] }) })] })));
3925
+ });
3926
+
3538
3927
  var defaultTranslations$8 = {
3539
3928
  previewAlt: "Vista previa de imagen",
3540
3929
  removeButtonAriaLabel: "Eliminar imagen",
@@ -10157,6 +10546,7 @@ exports.AuraAutocomplete = AuraAutocomplete;
10157
10546
  exports.AuraTable = AuraTable;
10158
10547
  exports.AuraToastProvider = AuraToastProvider;
10159
10548
  exports.BEWEOS_THEME_MODE_COOKIE_NAME = BEWEOS_THEME_MODE_COOKIE_NAME;
10549
+ exports.BetaBadge = BetaBadge;
10160
10550
  exports.BreadcrumbsComponent = BreadcrumbsComponent;
10161
10551
  exports.Button = Button;
10162
10552
  exports.CONTAINER_ATTRIBUTE = CONTAINER_ATTRIBUTE;
@@ -10189,8 +10579,11 @@ exports.InputPassword = InputPassword;
10189
10579
  exports.Kanban = Kanban;
10190
10580
  exports.KanbanCard = KanbanCard;
10191
10581
  exports.KanbanColumn = KanbanColumn;
10582
+ exports.LINDA_MASCOT_LEVEL_VAR = LINDA_MASCOT_LEVEL_VAR;
10583
+ exports.LINDA_MASCOT_STATES = LINDA_MASCOT_STATES;
10192
10584
  exports.LINDA_TONE_PROPERTIES = LINDA_TONE_PROPERTIES;
10193
10585
  exports.LindaIcon = LindaIcon;
10586
+ exports.LindaMascot = LindaMascot;
10194
10587
  exports.MenuClaw = MenuClaw;
10195
10588
  exports.MenuComponent = MenuComponent;
10196
10589
  exports.Modal = Modal;