@beweco/aurora-ui 1.0.1-qa.164 → 1.0.1-qa.166
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/assets/css/styles.css +2 -2
- package/dist/assets/css/theme.css +3 -1
- package/dist/index.cjs.js +1459 -416
- package/dist/index.esm.js +1438 -417
- package/dist/types/components/linda-mascot/LindaMascot.d.ts +7 -11
- package/dist/types/components/linda-mascot/LindaMascot.d.ts.map +1 -1
- package/dist/types/components/linda-mascot/LindaMascot.types.d.ts +44 -26
- package/dist/types/components/linda-mascot/LindaMascot.types.d.ts.map +1 -1
- package/dist/types/components/linda-mascot/character/character-color.d.ts +15 -0
- package/dist/types/components/linda-mascot/character/character-color.d.ts.map +1 -0
- package/dist/types/components/linda-mascot/character/character-css-vars.d.ts +29 -0
- package/dist/types/components/linda-mascot/character/character-css-vars.d.ts.map +1 -0
- package/dist/types/components/linda-mascot/character/character-normalize.d.ts +16 -0
- package/dist/types/components/linda-mascot/character/character-normalize.d.ts.map +1 -0
- package/dist/types/components/linda-mascot/character/character-palette.d.ts +78 -0
- package/dist/types/components/linda-mascot/character/character-palette.d.ts.map +1 -0
- package/dist/types/components/linda-mascot/character/character-platform.d.ts +26 -0
- package/dist/types/components/linda-mascot/character/character-platform.d.ts.map +1 -0
- package/dist/types/components/linda-mascot/character/character-themes.d.ts +51 -0
- package/dist/types/components/linda-mascot/character/character-themes.d.ts.map +1 -0
- package/dist/types/components/linda-mascot/character/fixtures/brand-example-character.d.ts +23 -0
- package/dist/types/components/linda-mascot/character/fixtures/brand-example-character.d.ts.map +1 -0
- package/dist/types/components/linda-mascot/character/index.d.ts +10 -0
- package/dist/types/components/linda-mascot/character/index.d.ts.map +1 -0
- package/dist/types/components/linda-mascot/index.d.ts +3 -2
- package/dist/types/components/linda-mascot/index.d.ts.map +1 -1
- package/dist/types/components/linda-mascot/linda-mascot.constants.d.ts +7 -44
- package/dist/types/components/linda-mascot/linda-mascot.constants.d.ts.map +1 -1
- package/dist/types/components/linda-mascot/linda-mascot.styles.d.ts +1 -0
- package/dist/types/components/linda-mascot/linda-mascot.styles.d.ts.map +1 -1
- package/dist/types/contexts/theme/theme-context.type.d.ts +1 -1
- package/dist/types/contexts/theme/theme-context.type.d.ts.map +1 -1
- package/dist/types/providers/theme/apply-custom-color.d.ts.map +1 -1
- package/dist/types/providers/theme/generate-color-scale.d.ts +21 -1
- package/dist/types/providers/theme/generate-color-scale.d.ts.map +1 -1
- package/dist/types/providers/theme/hex-to-theme-color.d.ts.map +1 -1
- package/dist/types/styles/colors.default.d.ts +70 -0
- package/dist/types/styles/colors.default.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs.js
CHANGED
|
@@ -471,7 +471,7 @@ const COLOR_TOKENS$1 = {
|
|
|
471
471
|
fg: "var(--color-primary-foreground)",
|
|
472
472
|
softBg: "var(--accent-soft)",
|
|
473
473
|
softBgHover: "var(--accent-soft-hover)",
|
|
474
|
-
softFg: "var(--
|
|
474
|
+
softFg: "var(--accent-soft-foreground)",
|
|
475
475
|
},
|
|
476
476
|
success: {
|
|
477
477
|
bg: "var(--success)",
|
|
@@ -1014,8 +1014,8 @@ const COLOR_TOKENS = {
|
|
|
1014
1014
|
bg: "var(--accent)",
|
|
1015
1015
|
fg: "var(--color-primary-foreground)",
|
|
1016
1016
|
flatBg: "color-mix(in srgb, var(--color-primary) 20%, transparent)",
|
|
1017
|
-
flatFg: "var(--
|
|
1018
|
-
tintFg: "var(--
|
|
1017
|
+
flatFg: "var(--accent-soft-foreground)",
|
|
1018
|
+
tintFg: "var(--accent-soft-foreground)",
|
|
1019
1019
|
},
|
|
1020
1020
|
success: {
|
|
1021
1021
|
bg: "var(--success)",
|
|
@@ -2896,7 +2896,7 @@ const AnalyticsCard = ({ data, showTimePeriods = true, showDropdownMenu = true,
|
|
|
2896
2896
|
return (jsxRuntime.jsx(Card, { className: "dark:border-default-100 border border-transparent", ...props, children: jsxRuntime.jsxs("section", { className: "flex flex-col flex-nowrap", children: [jsxRuntime.jsx("div", { className: "flex flex-col justify-between gap-y-2", children: jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-2", children: [jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-0", children: [jsxRuntime.jsx(H2, { children: t.title }), jsxRuntime.jsx(P, { children: t.description })] }), jsxRuntime.jsx("div", { className: "h-2", "aria-hidden": "true" }), showTimePeriods && (jsxRuntime.jsx(react.Tabs, { className: "self-end", onSelectionChange: (key) => handleTimePeriodChange(String(key)), children: jsxRuntime.jsx(react.Tabs.ListContainer, { className: "bg-default-100", children: jsxRuntime.jsxs(react.Tabs.List, { "aria-label": t.title, children: [jsxRuntime.jsxs(react.Tabs.Tab, { id: "6-months", className: "whitespace-nowrap", children: [t.months6, jsxRuntime.jsx(react.Tabs.Indicator, {})] }), jsxRuntime.jsxs(react.Tabs.Tab, { id: "3-months", className: "whitespace-nowrap", children: [t.months3, jsxRuntime.jsx(react.Tabs.Indicator, {})] }), jsxRuntime.jsxs(react.Tabs.Tab, { id: "30-days", className: "whitespace-nowrap", children: [t.days30, jsxRuntime.jsx(react.Tabs.Indicator, {})] }), jsxRuntime.jsxs(react.Tabs.Tab, { id: "7-days", className: "whitespace-nowrap", children: [t.days7, jsxRuntime.jsx(react.Tabs.Indicator, {})] }), jsxRuntime.jsxs(react.Tabs.Tab, { id: "24-hours", className: "whitespace-nowrap", children: [t.hours24, jsxRuntime.jsx(react.Tabs.Indicator, {})] })] }) }) })), showMetricCards && (jsxRuntime.jsx("div", { className: "mt-2 flex w-full items-center", children: jsxRuntime.jsx("div", { className: "-my-3 flex w-full max-w-[800px] items-center gap-x-3 overflow-x-auto py-3", children: data.map(({ key, change, changeType, type, value, title }) => (jsxRuntime.jsxs("button", { type: "button", className: cn("rounded-[12px] flex w-full flex-col gap-2 p-3 transition-colors", {
|
|
2897
2897
|
"bg-default-100": activeChart === key,
|
|
2898
2898
|
}), onClick: () => handleChartChange(key), children: [jsxRuntime.jsx("span", { className: cn("text-sm text-default-500 font-medium transition-colors", {
|
|
2899
|
-
"text-
|
|
2899
|
+
"text-accent-soft-foreground": activeChart === key,
|
|
2900
2900
|
}), children: title }), jsxRuntime.jsxs("div", { className: "flex items-center gap-x-3", children: [jsxRuntime.jsx("span", { className: "text-foreground text-2xl font-bold", children: formatValue(value, type) }), jsxRuntime.jsx(Chip, { color: changeType === "positive"
|
|
2901
2901
|
? "success"
|
|
2902
2902
|
: changeType === "negative"
|
|
@@ -4044,6 +4044,76 @@ const themeColors = {
|
|
|
4044
4044
|
overlay: "#ffffff",
|
|
4045
4045
|
},
|
|
4046
4046
|
},
|
|
4047
|
+
"amberYellow-light": {
|
|
4048
|
+
extend: "light",
|
|
4049
|
+
colors: {
|
|
4050
|
+
primary: {
|
|
4051
|
+
"50": "#FFFBE3",
|
|
4052
|
+
"100": "#FFF4BD",
|
|
4053
|
+
"200": "#FFEB92",
|
|
4054
|
+
"300": "#FFDC5E",
|
|
4055
|
+
"400": "#FFCF34",
|
|
4056
|
+
"500": "#FFBF00",
|
|
4057
|
+
"600": "#D8A200",
|
|
4058
|
+
"700": "#AC7E00",
|
|
4059
|
+
"800": "#805900",
|
|
4060
|
+
"900": "#533600",
|
|
4061
|
+
foreground: "#000",
|
|
4062
|
+
DEFAULT: "#FFBF00",
|
|
4063
|
+
},
|
|
4064
|
+
secondary: {
|
|
4065
|
+
"50": "#F3F7FD",
|
|
4066
|
+
"100": "#D1DFFB",
|
|
4067
|
+
"200": "#A5BEF7",
|
|
4068
|
+
"300": "#7494E7",
|
|
4069
|
+
"400": "#4E6FCF",
|
|
4070
|
+
"500": "#1E40AF",
|
|
4071
|
+
"600": "#153096",
|
|
4072
|
+
"700": "#0F237D",
|
|
4073
|
+
"800": "#091865",
|
|
4074
|
+
"900": "#051053",
|
|
4075
|
+
foreground: "#fff",
|
|
4076
|
+
DEFAULT: "#1E40AF",
|
|
4077
|
+
},
|
|
4078
|
+
focus: "#FFBF00",
|
|
4079
|
+
overlay: "#000000",
|
|
4080
|
+
},
|
|
4081
|
+
},
|
|
4082
|
+
"amberYellow-dark": {
|
|
4083
|
+
extend: "dark",
|
|
4084
|
+
colors: {
|
|
4085
|
+
primary: {
|
|
4086
|
+
"50": "#533600",
|
|
4087
|
+
"100": "#805900",
|
|
4088
|
+
"200": "#AC7E00",
|
|
4089
|
+
"300": "#D8A200",
|
|
4090
|
+
"400": "#FFBF00",
|
|
4091
|
+
"500": "#FFCF34",
|
|
4092
|
+
"600": "#FFDC5E",
|
|
4093
|
+
"700": "#FFEB92",
|
|
4094
|
+
"800": "#FFF4BD",
|
|
4095
|
+
"900": "#FFFBE3",
|
|
4096
|
+
foreground: "#000",
|
|
4097
|
+
DEFAULT: "#FFBF00",
|
|
4098
|
+
},
|
|
4099
|
+
secondary: {
|
|
4100
|
+
"50": "#002147",
|
|
4101
|
+
"100": "#003571",
|
|
4102
|
+
"200": "#00489b",
|
|
4103
|
+
"300": "#005cc4",
|
|
4104
|
+
"400": "#006fee",
|
|
4105
|
+
"500": "#2d88f1",
|
|
4106
|
+
"600": "#59a1f4",
|
|
4107
|
+
"700": "#86bbf7",
|
|
4108
|
+
"800": "#b3d4fa",
|
|
4109
|
+
"900": "#dfedfd",
|
|
4110
|
+
foreground: "#fff",
|
|
4111
|
+
DEFAULT: "#006fee",
|
|
4112
|
+
},
|
|
4113
|
+
focus: "#FFBF00",
|
|
4114
|
+
overlay: "#ffffff",
|
|
4115
|
+
},
|
|
4116
|
+
},
|
|
4047
4117
|
"coral-light": {
|
|
4048
4118
|
extend: "light",
|
|
4049
4119
|
colors: {
|
|
@@ -4552,7 +4622,7 @@ const themeColors = {
|
|
|
4552
4622
|
* Los mismos nombres de tema que resuelve HeroUI v3 (`@heroui/styles`):
|
|
4553
4623
|
* `:root, .light, .default, [data-theme=light], [data-theme=default]` para el claro y
|
|
4554
4624
|
* `.dark, [data-theme=dark]` para el oscuro. `default` es un alias del claro en v3; en v2 no
|
|
4555
|
-
* existía. Más los
|
|
4625
|
+
* existía. Más los 16 packs de aurora, cada uno en el lado de su `extend`, que son las clases
|
|
4556
4626
|
* que `theme-packs.generated.css` declara y `applyThemeClass` pone en `<html>`.
|
|
4557
4627
|
*/
|
|
4558
4628
|
const V3_ALIASES = {
|
|
@@ -6839,7 +6909,7 @@ const KanbanColumnComponent = ({ column, renderItem, onCardClick, cardClassName,
|
|
|
6839
6909
|
// siempre visible pero la story lo tapaba, y ahora queda apagado por defecto.
|
|
6840
6910
|
className: "static text-xs font-medium transform-none", style: column.countBadgeColor === "secondary"
|
|
6841
6911
|
? SECONDARY_BADGE_STYLE
|
|
6842
|
-
: undefined, "aria-label": `${itemCount} ${t.itemsLabel}`, children: itemCount }))] })), jsxRuntime.jsx("div", { ref: scrollContainerRef, className: cn("flex-1 overflow-y-auto p-3 space-y-3", isDragOver && isEmpty && "min-h-24"), style: { maxHeight }, children: isEmpty ? (isDragOver && isDragging ? (jsxRuntime.jsx("div", { className: "h-24 border-2 border-dashed border-primary-300 rounded-lg bg-primary-50/50 flex items-center justify-center", children: jsxRuntime.jsx("span", { className: "text-
|
|
6912
|
+
: undefined, "aria-label": `${itemCount} ${t.itemsLabel}`, children: itemCount }))] })), jsxRuntime.jsx("div", { ref: scrollContainerRef, className: cn("flex-1 overflow-y-auto p-3 space-y-3", isDragOver && isEmpty && "min-h-24"), style: { maxHeight }, children: isEmpty ? (isDragOver && isDragging ? (jsxRuntime.jsx("div", { className: "h-24 border-2 border-dashed border-primary-300 rounded-lg bg-primary-50/50 flex items-center justify-center", children: jsxRuntime.jsx("span", { className: "text-accent-soft-foreground text-sm", children: t.dropHere }) })) : renderEmptyState ? (renderEmptyState(column)) : (jsxRuntime.jsx("div", { className: "flex items-center justify-center h-24 text-default-400 text-sm", children: column.emptyMessage || t.emptyMessage }))) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [column.items.map((item, index) => (jsxRuntime.jsxs("div", { onDragOver: (e) => handleDragOverItem(e, index), children: [isDragOver && dropIndex === index && (jsxRuntime.jsx("div", { className: "h-1 bg-primary-400 rounded-full mb-3 animate-pulse" })), jsxRuntime.jsx(KanbanCard, { item: item, columnId: column.id, index: index, renderContent: renderItem, onCardClick: onCardClick, className: cardClassName, isClickable: isCardClickable, isDraggable: isDraggable, onDragStart: onDragStart, onDragEnd: onDragEnd })] }, item.id))), isDragOver && dropIndex === column.items.length && (jsxRuntime.jsx("div", { className: "h-1 bg-primary-400 rounded-full mt-3 animate-pulse" })), column.isLoading && (jsxRuntime.jsx("div", { className: "flex items-center justify-center py-4", children: jsxRuntime.jsx(react.Spinner, { size: "sm", color: "accent" }) }))] })) })] }));
|
|
6843
6913
|
};
|
|
6844
6914
|
const KanbanColumn = $8WNJc$react.memo(KanbanColumnComponent);
|
|
6845
6915
|
KanbanColumn.displayName = "KanbanColumn";
|
|
@@ -6949,14 +7019,394 @@ const LindaIcon = ({ size = 24, className, ...nativeProps }) => {
|
|
|
6949
7019
|
return (jsxRuntime.jsx("svg", { 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" })] }) }));
|
|
6950
7020
|
};
|
|
6951
7021
|
|
|
7022
|
+
/** Aritmética mínima de color del personaje. TS puro: sin DOM ni React. */
|
|
7023
|
+
const HEX = /^#(?:[0-9a-f]{3}|[0-9a-f]{6})$/i;
|
|
7024
|
+
/**
|
|
7025
|
+
* Un color en HEX normalizado a `#RRGGBB` en mayúsculas, o `null` si no lo es.
|
|
7026
|
+
*
|
|
7027
|
+
* Acepta `#RGB` y `#RRGGBB` en cualquier caja y con espacios alrededor; cualquier otra
|
|
7028
|
+
* cosa (un nombre, `rgb()`, un hex con alfa, un no-texto) devuelve `null` para que quien
|
|
7029
|
+
* llama decida el respaldo en vez de pintar un color que el navegador no entiende.
|
|
7030
|
+
*/
|
|
7031
|
+
const normalizeHex = (value) => {
|
|
7032
|
+
if (typeof value !== "string") {
|
|
7033
|
+
return null;
|
|
7034
|
+
}
|
|
7035
|
+
const trimmed = value.trim();
|
|
7036
|
+
if (!HEX.test(trimmed)) {
|
|
7037
|
+
return null;
|
|
7038
|
+
}
|
|
7039
|
+
const digits = trimmed.slice(1);
|
|
7040
|
+
const full = digits.length === 3
|
|
7041
|
+
? digits
|
|
7042
|
+
.split("")
|
|
7043
|
+
.map((digit) => digit + digit)
|
|
7044
|
+
.join("")
|
|
7045
|
+
: digits;
|
|
7046
|
+
return `#${full.toUpperCase()}`;
|
|
7047
|
+
};
|
|
7048
|
+
/**
|
|
7049
|
+
* Aclara un color hacia el blanco canal a canal: `0` lo deja igual y `1` es blanco.
|
|
7050
|
+
* Espera un HEX ya normalizado.
|
|
7051
|
+
*/
|
|
7052
|
+
const tintHex = (hex, amount) => {
|
|
7053
|
+
const value = Number.parseInt(hex.slice(1), 16);
|
|
7054
|
+
const channels = [(value >> 16) & 255, (value >> 8) & 255, value & 255];
|
|
7055
|
+
return `#${channels
|
|
7056
|
+
.map((channel) => Math.round(channel + (255 - channel) * amount)
|
|
7057
|
+
.toString(16)
|
|
7058
|
+
.padStart(2, "0"))
|
|
7059
|
+
.join("")
|
|
7060
|
+
.toUpperCase()}`;
|
|
7061
|
+
};
|
|
7062
|
+
|
|
7063
|
+
/**
|
|
7064
|
+
* Los temas del personaje de Linda: el dato de color del agente.
|
|
7065
|
+
*
|
|
7066
|
+
* Un tema son **9 colores con rol** del lienzo de diseño. La anatomía, los estados y las
|
|
7067
|
+
* animaciones son los mismos en todos; lo único que cambia son estos colores. Aquí está
|
|
7068
|
+
* el único sitio de la librería donde se escriben los hex de un tema: el componente los
|
|
7069
|
+
* recibe por variables CSS (ver `character-css-vars.ts`).
|
|
7070
|
+
*
|
|
7071
|
+
* Las claves de los roles son las mismas que guarda y sirve el backend de agencias, para
|
|
7072
|
+
* que lo que llega por la API se pueda pasar tal cual a `characterPaletteFromTheme`.
|
|
7073
|
+
*/
|
|
7074
|
+
/** Los 9 roles de un tema, en el orden de la tabla del diseño. */
|
|
7075
|
+
const CHARACTER_THEME_COLOR_KEYS = [
|
|
7076
|
+
/** Accent AI: scoring y micro-detalles de inteligencia. */
|
|
7077
|
+
"accent",
|
|
7078
|
+
/** Primary: acción principal y control humano. */
|
|
7079
|
+
"primary",
|
|
7080
|
+
/** Cian de navegación: fondos destacados y navegación activa. */
|
|
7081
|
+
"navigation",
|
|
7082
|
+
/** Aqua suave: fondo general y contenedores amplios. */
|
|
7083
|
+
"soft",
|
|
7084
|
+
/** Teal neutro: apoyo, divisores y estados neutros. */
|
|
7085
|
+
"neutral",
|
|
7086
|
+
/** Secondary (verde de crecimiento): éxito, clientes activos, automatizaciones. */
|
|
7087
|
+
"secondary",
|
|
7088
|
+
/** Contexto AI: propuestas proactivas. */
|
|
7089
|
+
"context",
|
|
7090
|
+
/** Superficie profunda: tarjetas oscuras y datos secundarios. */
|
|
7091
|
+
"surface",
|
|
7092
|
+
/** Base oscura: núcleo, tipografía, encabezados y menús. */
|
|
7093
|
+
"base",
|
|
7094
|
+
];
|
|
7095
|
+
const CHARACTER_THEME_IDS = [
|
|
7096
|
+
"linda",
|
|
7097
|
+
"luna",
|
|
7098
|
+
"purple",
|
|
7099
|
+
"coral",
|
|
7100
|
+
"green",
|
|
7101
|
+
"ocean",
|
|
7102
|
+
"sky",
|
|
7103
|
+
"yellow",
|
|
7104
|
+
];
|
|
7105
|
+
/** El tema de Bewe y el que se usa cuando no hay otro. */
|
|
7106
|
+
const DEFAULT_CHARACTER_THEME_ID = "linda";
|
|
7107
|
+
const theme = (id, name, values, outline) => {
|
|
7108
|
+
const hexes = values.split(" ");
|
|
7109
|
+
const colors = Object.fromEntries(CHARACTER_THEME_COLOR_KEYS.map((key, index) => [key, hexes[index]]));
|
|
7110
|
+
return Object.freeze({
|
|
7111
|
+
id,
|
|
7112
|
+
name,
|
|
7113
|
+
colors: Object.freeze({ ...colors, outline }),
|
|
7114
|
+
});
|
|
7115
|
+
};
|
|
7116
|
+
/**
|
|
7117
|
+
* Los 8 temas del lienzo. Valores en el orden de `CHARACTER_THEME_COLOR_KEYS`; el último
|
|
7118
|
+
* argumento es el filo del aro de cada tema (`.rimline` en las páginas de Estados).
|
|
7119
|
+
* Congelados en profundidad: son el respaldo de toda paleta incompleta.
|
|
7120
|
+
*/
|
|
7121
|
+
const CHARACTER_THEMES = Object.freeze({
|
|
7122
|
+
linda: theme("linda", "Linda", "#FAD19E #60A5FA #67E8F9 #CCFBF1 #75C9C8 #34D399 #FEF3C7 #355452 #0A2540", "#B4E1FC"),
|
|
7123
|
+
luna: theme("luna", "Luna", "#D29EF6 #A133EB #C27AF2 #F2E4F9 #ACA0B1 #7F6D87 #F2E4F9 #534758 #262128", "#E3C2F9"),
|
|
7124
|
+
purple: theme("purple", "Purple", "#A773DB #7828C8 #59A1F4 #EEE4F8 #86BBF7 #006FEE #DFEDFD #39135F #240C3C", "#B3D4FA"),
|
|
7125
|
+
coral: theme("coral", "Coral", "#FF6E6E #FF4F4F #FF8D8D #FFE9E9 #FFABAB #D24141 #FFCACA #792626 #4C1818", "#FFCACA"),
|
|
7126
|
+
green: theme("green", "Green", "#7E91FB #16C964 #68DC9A #E2F8EC #90E5B5 #3956F9 #E6EAFE #1B2976 #111A4B", "#B9EFD0"),
|
|
7127
|
+
ocean: theme("ocean", "Ocean", "#6AF5BB #26A5E5 #72C4EE #E4F4FC #98D4F3 #1AEF96 #E2FDF2 #124E6D #0B3245", "#BEE4F7"),
|
|
7128
|
+
sky: theme("sky", "Sky", "#FAD19E #60A5FA #98C5FC #EBF4FE #7CB5FB #7ACA97 #FEF1E2 #2E4E77 #1D324B", "#CFE4FE"),
|
|
7129
|
+
yellow: theme("yellow", "Yellow", "#FFD505 #4561BD #6D83CB #FFFAE0 #94A4D9 #D2B004 #FFF2B4 #0E1E53 #091334", "#BCC6E7"),
|
|
7130
|
+
});
|
|
7131
|
+
/**
|
|
7132
|
+
* Los colores fijos del personaje, iguales en todos los temas: el aviso (naranja, su
|
|
7133
|
+
* tono suave y el rojo del borde) y el blanco de ojos y brillos.
|
|
7134
|
+
*/
|
|
7135
|
+
const CHARACTER_FIXED_COLORS = {
|
|
7136
|
+
alert: "#F97316",
|
|
7137
|
+
alertSoft: "#FB923C",
|
|
7138
|
+
alertDeep: "#EF4444",
|
|
7139
|
+
light: "#FFFFFF",
|
|
7140
|
+
};
|
|
7141
|
+
|
|
7142
|
+
/** Cuánto se aclara el Primary para el filo del aro cuando los colores son propios. */
|
|
7143
|
+
const OUTLINE_TINT = 0.7;
|
|
7144
|
+
/**
|
|
7145
|
+
* Valida los colores de un tema y completa lo que falte con los de Linda, rol a rol.
|
|
7146
|
+
*
|
|
7147
|
+
* Una configuración incompleta (un rol sin enviar, un color mal escrito) nunca deja el
|
|
7148
|
+
* personaje sin color: ese rol sale como el de Linda y se informa en `issues`. El filo
|
|
7149
|
+
* (`outline`) solo se conserva si es un HEX válido; si no, se omite y lo resuelve la
|
|
7150
|
+
* derivación.
|
|
7151
|
+
*/
|
|
7152
|
+
const normalizeCharacterThemeColors = (input) => {
|
|
7153
|
+
const source = input !== null && typeof input === "object"
|
|
7154
|
+
? input
|
|
7155
|
+
: {};
|
|
7156
|
+
const fallback = CHARACTER_THEMES[DEFAULT_CHARACTER_THEME_ID].colors;
|
|
7157
|
+
const issues = [];
|
|
7158
|
+
const colors = {};
|
|
7159
|
+
for (const key of CHARACTER_THEME_COLOR_KEYS) {
|
|
7160
|
+
const hex = normalizeHex(source[key]);
|
|
7161
|
+
if (hex) {
|
|
7162
|
+
colors[key] = hex;
|
|
7163
|
+
}
|
|
7164
|
+
else {
|
|
7165
|
+
colors[key] = fallback[key];
|
|
7166
|
+
issues.push({
|
|
7167
|
+
key,
|
|
7168
|
+
reason: source[key] === undefined ? "missing" : "invalid",
|
|
7169
|
+
});
|
|
7170
|
+
}
|
|
7171
|
+
}
|
|
7172
|
+
const outline = normalizeHex(source.outline);
|
|
7173
|
+
if (outline) {
|
|
7174
|
+
colors.outline = outline;
|
|
7175
|
+
}
|
|
7176
|
+
else if (source.outline !== undefined && source.outline !== null) {
|
|
7177
|
+
issues.push({ key: "outline", reason: "invalid" });
|
|
7178
|
+
}
|
|
7179
|
+
return { colors, issues };
|
|
7180
|
+
};
|
|
7181
|
+
/**
|
|
7182
|
+
* El filo del aro de un tema del lienzo si los 9 colores son exactamente los suyos.
|
|
7183
|
+
*
|
|
7184
|
+
* El backend guarda 9 colores y no el filo, que el diseño ajusta a mano por tema y no sale
|
|
7185
|
+
* de ninguna regla. Así un tema elegido en el panel se pinta igual que en el lienzo.
|
|
7186
|
+
*/
|
|
7187
|
+
const outlineOfMatchingTheme = (colors) => {
|
|
7188
|
+
const match = CHARACTER_THEME_IDS.find((id) => CHARACTER_THEME_COLOR_KEYS.every((key) => CHARACTER_THEMES[id].colors[key] === colors[key]));
|
|
7189
|
+
return match ? CHARACTER_THEMES[match].colors.outline : undefined;
|
|
7190
|
+
};
|
|
7191
|
+
/**
|
|
7192
|
+
* Los 9 colores de un tema repartidos por las piezas del dibujo.
|
|
7193
|
+
*
|
|
7194
|
+
* Es la regla del lienzo: el aro recorre Primary → Cian → Secondary → Accent y vuelve; al
|
|
7195
|
+
* pensar se enfría hacia Teal y Aqua; el núcleo es la Base; la película de la pompa pasa
|
|
7196
|
+
* por Aqua, Contexto, Accent, Primary y Cian. El aviso y el blanco son fijos, salvo el
|
|
7197
|
+
* tercer tono del aro de aviso, que es el Accent del tema.
|
|
7198
|
+
*
|
|
7199
|
+
* Tolera entradas incompletas o inválidas: cada rol que no se entienda sale como el de
|
|
7200
|
+
* Linda (ver `normalizeCharacterThemeColors`).
|
|
7201
|
+
*/
|
|
7202
|
+
const characterPaletteFromTheme = (input) => {
|
|
7203
|
+
const { colors } = normalizeCharacterThemeColors(input);
|
|
7204
|
+
const { accent, primary, navigation, soft, neutral, secondary, context, base, } = colors;
|
|
7205
|
+
const { alert, alertSoft, alertDeep, light } = CHARACTER_FIXED_COLORS;
|
|
7206
|
+
return {
|
|
7207
|
+
ring: [
|
|
7208
|
+
primary,
|
|
7209
|
+
navigation,
|
|
7210
|
+
secondary,
|
|
7211
|
+
accent,
|
|
7212
|
+
secondary,
|
|
7213
|
+
navigation,
|
|
7214
|
+
primary,
|
|
7215
|
+
],
|
|
7216
|
+
thinkingRing: [navigation, primary, neutral, soft, navigation],
|
|
7217
|
+
alertRing: [alert, alertSoft, accent, alert, alertDeep, alert],
|
|
7218
|
+
core: base,
|
|
7219
|
+
film: [soft, context, accent, primary, navigation],
|
|
7220
|
+
light,
|
|
7221
|
+
mint: soft,
|
|
7222
|
+
glow: navigation,
|
|
7223
|
+
deep: primary,
|
|
7224
|
+
spark: secondary,
|
|
7225
|
+
warm: accent,
|
|
7226
|
+
outline: colors.outline ??
|
|
7227
|
+
outlineOfMatchingTheme(colors) ??
|
|
7228
|
+
tintHex(primary, OUTLINE_TINT),
|
|
7229
|
+
alert,
|
|
7230
|
+
alertDeep,
|
|
7231
|
+
};
|
|
7232
|
+
};
|
|
7233
|
+
const lindaPalette = characterPaletteFromTheme(CHARACTER_THEMES[DEFAULT_CHARACTER_THEME_ID].colors);
|
|
7234
|
+
for (const value of Object.values(lindaPalette)) {
|
|
7235
|
+
if (Array.isArray(value)) {
|
|
7236
|
+
Object.freeze(value);
|
|
7237
|
+
}
|
|
7238
|
+
}
|
|
7239
|
+
/**
|
|
7240
|
+
* La paleta de Linda: el respaldo de todo lo que no se entienda. Congelada, porque todas
|
|
7241
|
+
* las mascotas caen a ella: modificarla desde fuera cambiaría el respaldo de todas.
|
|
7242
|
+
*/
|
|
7243
|
+
const DEFAULT_CHARACTER_PALETTE = Object.freeze(lindaPalette);
|
|
7244
|
+
|
|
7245
|
+
const LIST_KEYS = ["ring", "thinkingRing", "alertRing", "film"];
|
|
7246
|
+
/**
|
|
7247
|
+
* Tonos mínimos de cada lista. Un aro es un degradado que da la vuelta: con un solo tono
|
|
7248
|
+
* no hay degradado (y hay navegadores que descartan uno de una sola parada, dejando el aro
|
|
7249
|
+
* sin pintar). La película sí admite uno: los huecos repiten su primer tono.
|
|
7250
|
+
*/
|
|
7251
|
+
const MIN_LENGTH = {
|
|
7252
|
+
ring: 2,
|
|
7253
|
+
thinkingRing: 2,
|
|
7254
|
+
alertRing: 2,
|
|
7255
|
+
film: 1,
|
|
7256
|
+
};
|
|
7257
|
+
const COLOR_KEYS = [
|
|
7258
|
+
"core",
|
|
7259
|
+
"light",
|
|
7260
|
+
"mint",
|
|
7261
|
+
"glow",
|
|
7262
|
+
"deep",
|
|
7263
|
+
"spark",
|
|
7264
|
+
"warm",
|
|
7265
|
+
"outline",
|
|
7266
|
+
"alert",
|
|
7267
|
+
"alertDeep",
|
|
7268
|
+
];
|
|
7269
|
+
/**
|
|
7270
|
+
* Valida una paleta ya repartida (la de la app, una guardada, la que llega por props) y
|
|
7271
|
+
* la completa con la de Linda pieza por pieza.
|
|
7272
|
+
*
|
|
7273
|
+
* Un campo suelto que no sea un HEX cae al de Linda. Una lista que no sea un array de HEX
|
|
7274
|
+
* válidos (al menos dos en los aros) cae ENTERA a la de Linda: mezclar tonos de dos temas en el mismo
|
|
7275
|
+
* aro se ve como un error, no como un tema. Nunca lanza.
|
|
7276
|
+
*/
|
|
7277
|
+
const normalizeCharacterPalette = (input) => {
|
|
7278
|
+
const source = input !== null && typeof input === "object"
|
|
7279
|
+
? input
|
|
7280
|
+
: {};
|
|
7281
|
+
const issues = [];
|
|
7282
|
+
const palette = { ...DEFAULT_CHARACTER_PALETTE };
|
|
7283
|
+
for (const key of LIST_KEYS) {
|
|
7284
|
+
const value = source[key];
|
|
7285
|
+
const hexes = Array.isArray(value) ? value.map(normalizeHex) : [];
|
|
7286
|
+
if (hexes.length >= MIN_LENGTH[key] && hexes.every((hex) => hex !== null)) {
|
|
7287
|
+
palette[key] = hexes;
|
|
7288
|
+
}
|
|
7289
|
+
else {
|
|
7290
|
+
palette[key] = [...DEFAULT_CHARACTER_PALETTE[key]];
|
|
7291
|
+
issues.push({ key, reason: value === undefined ? "missing" : "invalid" });
|
|
7292
|
+
}
|
|
7293
|
+
}
|
|
7294
|
+
for (const key of COLOR_KEYS) {
|
|
7295
|
+
const hex = normalizeHex(source[key]);
|
|
7296
|
+
if (hex) {
|
|
7297
|
+
palette[key] = hex;
|
|
7298
|
+
}
|
|
7299
|
+
else {
|
|
7300
|
+
issues.push({
|
|
7301
|
+
key,
|
|
7302
|
+
reason: source[key] === undefined ? "missing" : "invalid",
|
|
7303
|
+
});
|
|
7304
|
+
}
|
|
7305
|
+
}
|
|
7306
|
+
return { palette, issues };
|
|
7307
|
+
};
|
|
7308
|
+
/** `true` si la paleta está completa y todos sus colores son HEX válidos. */
|
|
7309
|
+
const isCompleteCharacterPalette = (input) => normalizeCharacterPalette(input).issues.length === 0;
|
|
7310
|
+
|
|
7311
|
+
/**
|
|
7312
|
+
* Las variables CSS que lee `LindaMascot`. Las listas (`--lm-ring`…) van separadas por
|
|
7313
|
+
* comas para entrar tal cual en un `conic-gradient`. `--lm-teal` y `--lm-alert-soft` no
|
|
7314
|
+
* son campos de la paleta: salen de ella (el tercer tono del aro de pensar y el segundo
|
|
7315
|
+
* del de aviso), igual que hace la app con las órbitas.
|
|
7316
|
+
*/
|
|
7317
|
+
const CHARACTER_CSS_VARS = [
|
|
7318
|
+
"--lm-ring",
|
|
7319
|
+
"--lm-thinking-ring",
|
|
7320
|
+
"--lm-alert-ring",
|
|
7321
|
+
"--lm-core",
|
|
7322
|
+
"--lm-film-1",
|
|
7323
|
+
"--lm-film-2",
|
|
7324
|
+
"--lm-film-3",
|
|
7325
|
+
"--lm-film-4",
|
|
7326
|
+
"--lm-film-5",
|
|
7327
|
+
"--lm-light",
|
|
7328
|
+
"--lm-mint",
|
|
7329
|
+
"--lm-glow",
|
|
7330
|
+
"--lm-deep",
|
|
7331
|
+
"--lm-spark",
|
|
7332
|
+
"--lm-warm",
|
|
7333
|
+
"--lm-outline",
|
|
7334
|
+
"--lm-alert",
|
|
7335
|
+
"--lm-alert-deep",
|
|
7336
|
+
"--lm-teal",
|
|
7337
|
+
"--lm-alert-soft",
|
|
7338
|
+
];
|
|
7339
|
+
/**
|
|
7340
|
+
* Una paleta como variables CSS, lista para un `style` o para `setProperty`. Normaliza
|
|
7341
|
+
* antes: lo que no se entienda sale con los colores de Linda.
|
|
7342
|
+
*/
|
|
7343
|
+
const characterPaletteToCssVars = (input) => {
|
|
7344
|
+
const { palette } = normalizeCharacterPalette(input);
|
|
7345
|
+
const film = (index) => palette.film[index] ?? palette.film[0];
|
|
7346
|
+
return {
|
|
7347
|
+
"--lm-ring": palette.ring.join(", "),
|
|
7348
|
+
"--lm-thinking-ring": palette.thinkingRing.join(", "),
|
|
7349
|
+
"--lm-alert-ring": palette.alertRing.join(", "),
|
|
7350
|
+
"--lm-core": palette.core,
|
|
7351
|
+
"--lm-film-1": film(0),
|
|
7352
|
+
"--lm-film-2": film(1),
|
|
7353
|
+
"--lm-film-3": film(2),
|
|
7354
|
+
"--lm-film-4": film(3),
|
|
7355
|
+
"--lm-film-5": film(4),
|
|
7356
|
+
"--lm-light": palette.light,
|
|
7357
|
+
"--lm-mint": palette.mint,
|
|
7358
|
+
"--lm-glow": palette.glow,
|
|
7359
|
+
"--lm-deep": palette.deep,
|
|
7360
|
+
"--lm-spark": palette.spark,
|
|
7361
|
+
"--lm-warm": palette.warm,
|
|
7362
|
+
"--lm-outline": palette.outline,
|
|
7363
|
+
"--lm-alert": palette.alert,
|
|
7364
|
+
"--lm-alert-deep": palette.alertDeep,
|
|
7365
|
+
"--lm-teal": palette.thinkingRing[2] ?? palette.thinkingRing[0],
|
|
7366
|
+
"--lm-alert-soft": palette.alertRing[1],
|
|
7367
|
+
};
|
|
7368
|
+
};
|
|
7369
|
+
/**
|
|
7370
|
+
* Escribe la paleta del personaje en un elemento, típicamente
|
|
7371
|
+
* `document.documentElement.style` para que todas las mascotas de la página la hereden.
|
|
7372
|
+
*/
|
|
7373
|
+
const applyCharacterPalette = (style, palette) => {
|
|
7374
|
+
for (const [name, value] of Object.entries(characterPaletteToCssVars(palette))) {
|
|
7375
|
+
style.setProperty(name, value);
|
|
7376
|
+
}
|
|
7377
|
+
};
|
|
7378
|
+
/** Quita la paleta: las mascotas vuelven a pintarse con la de Linda. */
|
|
7379
|
+
const removeCharacterPalette = (style) => {
|
|
7380
|
+
for (const name of CHARACTER_CSS_VARS) {
|
|
7381
|
+
style.removeProperty(name);
|
|
7382
|
+
}
|
|
7383
|
+
};
|
|
7384
|
+
|
|
7385
|
+
/** Los estados que se pintan, en el orden del lienzo de diseño. */
|
|
6952
7386
|
const LINDA_MASCOT_STATES = [
|
|
6953
|
-
"
|
|
6954
|
-
"
|
|
7387
|
+
"ready",
|
|
7388
|
+
"thinking",
|
|
6955
7389
|
"working",
|
|
6956
7390
|
"listening",
|
|
7391
|
+
"alert",
|
|
7392
|
+
"loading",
|
|
6957
7393
|
"talking",
|
|
6958
|
-
"ready",
|
|
6959
7394
|
];
|
|
7395
|
+
/** Nombres anteriores de estado y el estado con el que se pintan ahora. */
|
|
7396
|
+
const LINDA_MASCOT_STATE_ALIASES = {
|
|
7397
|
+
idle: "ready",
|
|
7398
|
+
processing: "thinking",
|
|
7399
|
+
};
|
|
7400
|
+
/** El estado que se pinta. Un nombre anterior se traduce; uno desconocido, reposo. */
|
|
7401
|
+
const resolveMascotState = (state) => {
|
|
7402
|
+
if (state === undefined) {
|
|
7403
|
+
return "ready";
|
|
7404
|
+
}
|
|
7405
|
+
if (state === "idle" || state === "processing") {
|
|
7406
|
+
return LINDA_MASCOT_STATE_ALIASES[state];
|
|
7407
|
+
}
|
|
7408
|
+
return LINDA_MASCOT_STATES.includes(state) ? state : "ready";
|
|
7409
|
+
};
|
|
6960
7410
|
/** px de cada talla con nombre. Cada una cae en su propio nivel de detalle. */
|
|
6961
7411
|
const LINDA_MASCOT_SIZE_PX = {
|
|
6962
7412
|
xs: 20,
|
|
@@ -6968,17 +7418,6 @@ const LINDA_MASCOT_SIZE_PX = {
|
|
|
6968
7418
|
const LINDA_MASCOT_LEVEL_VAR = "--linda-mascot-level";
|
|
6969
7419
|
/** id de la `<style>` que el componente deja en `<head>`. */
|
|
6970
7420
|
const LINDA_MASCOT_STYLE_ID = "aurora-linda-mascot-styles";
|
|
6971
|
-
/** Paleta de la hoja de marca. */
|
|
6972
|
-
const LINDA_MASCOT_PALETTE = {
|
|
6973
|
-
coreLight: "#2A2D4A",
|
|
6974
|
-
coreDark: "#0B0C18",
|
|
6975
|
-
eye: "#EAF2FF",
|
|
6976
|
-
eyeGlow: "#8FB8FF",
|
|
6977
|
-
pink: "#FF8AD8",
|
|
6978
|
-
violet: "#A48BFF",
|
|
6979
|
-
cyan: "#6FE3FF",
|
|
6980
|
-
amber: "#FFD08A",
|
|
6981
|
-
};
|
|
6982
7421
|
const resolveMascotPx = (size) => {
|
|
6983
7422
|
if (typeof size === "number") {
|
|
6984
7423
|
return Number.isFinite(size) && size > 0 ? size : LINDA_MASCOT_SIZE_PX.md;
|
|
@@ -7004,480 +7443,952 @@ const clampLevel = (level) => {
|
|
|
7004
7443
|
}
|
|
7005
7444
|
return Math.min(1, Math.max(0, level));
|
|
7006
7445
|
};
|
|
7007
|
-
const LINDA_MASCOT_GEOMETRY = {
|
|
7008
|
-
xs: {
|
|
7009
|
-
coreRx: 40,
|
|
7010
|
-
coreCy: 61,
|
|
7011
|
-
eyeWidth: 17,
|
|
7012
|
-
eyeHeight: 8,
|
|
7013
|
-
eyeStroke: 9,
|
|
7014
|
-
eyeGap: 31,
|
|
7015
|
-
rings: [{ r: 57, squash: 0.3, tilt: -16, strokePx: 1.2, opacity: 0.95 }],
|
|
7016
|
-
halo: false,
|
|
7017
|
-
specular: false,
|
|
7018
|
-
blur: false,
|
|
7019
|
-
ringGlow: "none",
|
|
7020
|
-
},
|
|
7021
|
-
sm: {
|
|
7022
|
-
coreRx: 36,
|
|
7023
|
-
coreCy: 61,
|
|
7024
|
-
eyeWidth: 14,
|
|
7025
|
-
eyeHeight: 6.5,
|
|
7026
|
-
eyeStroke: 6,
|
|
7027
|
-
eyeGap: 28,
|
|
7028
|
-
rings: [
|
|
7029
|
-
{ r: 56, squash: 0.3, tilt: -16, strokePx: 1.1, opacity: 0.9 },
|
|
7030
|
-
{ r: 52, squash: 0.36, tilt: 20, strokePx: 1, opacity: 0.7 },
|
|
7031
|
-
],
|
|
7032
|
-
halo: true,
|
|
7033
|
-
specular: false,
|
|
7034
|
-
blur: false,
|
|
7035
|
-
ringGlow: "none",
|
|
7036
|
-
},
|
|
7037
|
-
md: {
|
|
7038
|
-
coreRx: 33,
|
|
7039
|
-
coreCy: 61,
|
|
7040
|
-
eyeWidth: 12.5,
|
|
7041
|
-
eyeHeight: 5.5,
|
|
7042
|
-
eyeStroke: 4.4,
|
|
7043
|
-
eyeGap: 25,
|
|
7044
|
-
rings: [
|
|
7045
|
-
{ r: 56, squash: 0.3, tilt: -16, strokePx: 1.5, opacity: 0.85 },
|
|
7046
|
-
{ r: 52, squash: 0.38, tilt: 20, strokePx: 1.2, opacity: 0.7 },
|
|
7047
|
-
{ r: 58, squash: 0.2, tilt: -3, strokePx: 1, opacity: 0.55 },
|
|
7048
|
-
],
|
|
7049
|
-
halo: true,
|
|
7050
|
-
specular: true,
|
|
7051
|
-
blur: true,
|
|
7052
|
-
ringGlow: "flat",
|
|
7053
|
-
},
|
|
7054
|
-
lg: {
|
|
7055
|
-
coreRx: 32,
|
|
7056
|
-
coreCy: 61,
|
|
7057
|
-
eyeWidth: 12,
|
|
7058
|
-
eyeHeight: 5.2,
|
|
7059
|
-
eyeStroke: 3.8,
|
|
7060
|
-
eyeGap: 24,
|
|
7061
|
-
rings: [
|
|
7062
|
-
{ r: 56, squash: 0.3, tilt: -16, strokePx: 2, opacity: 0.85 },
|
|
7063
|
-
{ r: 52, squash: 0.38, tilt: 20, strokePx: 1.6, opacity: 0.72 },
|
|
7064
|
-
{ r: 58, squash: 0.2, tilt: -3, strokePx: 1.3, opacity: 0.58 },
|
|
7065
|
-
],
|
|
7066
|
-
halo: true,
|
|
7067
|
-
specular: true,
|
|
7068
|
-
blur: true,
|
|
7069
|
-
ringGlow: "blur",
|
|
7070
|
-
},
|
|
7071
|
-
};
|
|
7072
7446
|
|
|
7447
|
+
/**
|
|
7448
|
+
* La hoja del personaje: el lienzo de diseño (variante «pompa de jabón») aplanado.
|
|
7449
|
+
*
|
|
7450
|
+
* El lienzo es HTML + CSS con una cascada larga de refinados; aquí está solo lo que de
|
|
7451
|
+
* verdad se ve, resuelto regla a regla, con tres cambios:
|
|
7452
|
+
*
|
|
7453
|
+
* - **Ningún color escrito.** Cada color de tema sale de una variable `--_lm-*`, que lee la
|
|
7454
|
+
* pública `--lm-*` (la escribe `applyCharacterPalette` o la prop `palette`) con la paleta
|
|
7455
|
+
* de Linda como respaldo, generada desde el dato del tema. Los tonos con transparencia
|
|
7456
|
+
* del lienzo (`rgba(<rol>, .35)`) son `color-mix` de esas variables. Solo el blanco y el
|
|
7457
|
+
* negro de brillos y sombras van escritos.
|
|
7458
|
+
* - **Mide en `cqmin`.** El lienzo multiplica todo por `--s` (el lado). Aquí el lado es la
|
|
7459
|
+
* caja de la raíz (`container-type: size`), así que el dibujo sigue a la caja aunque el
|
|
7460
|
+
* consumidor la cambie por CSS (`size-full` en la llamada de Claw). La talla de la prop va
|
|
7461
|
+
* en \`@layer base\` para que esa clase gane.
|
|
7462
|
+
* - **Sin `!important` en las animaciones.** El lienzo resolvía su cascada con `!important`
|
|
7463
|
+
* y selectores de id; aquí cada estado gana por especificidad y el único `!important` es
|
|
7464
|
+
* el del movimiento reducido, que así para todo.
|
|
7465
|
+
*/
|
|
7466
|
+
const ROOT = ".aurora-linda-mascot";
|
|
7073
7467
|
const LEVEL = `var(${LINDA_MASCOT_LEVEL_VAR})`;
|
|
7074
|
-
|
|
7075
|
-
|
|
7076
|
-
|
|
7077
|
-
|
|
7078
|
-
|
|
7079
|
-
|
|
7080
|
-
|
|
7081
|
-
|
|
7082
|
-
|
|
7083
|
-
|
|
7084
|
-
|
|
7085
|
-
|
|
7086
|
-
|
|
7087
|
-
|
|
7088
|
-
|
|
7089
|
-
const
|
|
7090
|
-
|
|
7091
|
-
|
|
7092
|
-
|
|
7093
|
-
|
|
7094
|
-
|
|
7095
|
-
|
|
7096
|
-
|
|
7468
|
+
/** Una medida del lienzo: fracción del lado. */
|
|
7469
|
+
const s = (k) => `calc(var(--_lm-s) * ${k})`;
|
|
7470
|
+
/** Un color de tema con transparencia. */
|
|
7471
|
+
const mix = (name, percent) => `color-mix(in srgb, var(--_lm-${name}) ${percent}%, transparent)`;
|
|
7472
|
+
const white = (alpha) => `rgba(255, 255, 255, ${alpha})`;
|
|
7473
|
+
const black = (alpha) => `rgba(0, 0, 0, ${alpha})`;
|
|
7474
|
+
/** Huevo del aro y del núcleo. */
|
|
7475
|
+
const EGG = "50% 50% 46% 46% / 54% 54% 46% 46%";
|
|
7476
|
+
/** La pompa en reposo. */
|
|
7477
|
+
const BUBBLE_SHAPE = "63% 37% 54% 46% / 43% 60% 40% 57%";
|
|
7478
|
+
/** Máscara que deja solo el borde de una caja (el aro). */
|
|
7479
|
+
const BORDER_ONLY = `-webkit-mask: linear-gradient(black 0 0) padding-box, linear-gradient(black 0 0);
|
|
7480
|
+
-webkit-mask-composite: xor;
|
|
7481
|
+
mask: linear-gradient(black 0 0) padding-box, linear-gradient(black 0 0);
|
|
7482
|
+
mask-composite: exclude;`;
|
|
7483
|
+
const SOFT_EASE = "cubic-bezier(0.45, 0.05, 0.55, 0.95)";
|
|
7484
|
+
/**
|
|
7485
|
+
* `--_lm-x: var(--lm-x, <Linda>);` por cada variable pública. Una línea por variable: el
|
|
7486
|
+
* test que vigila que no haya colores escritos se salta exactamente estas líneas.
|
|
7487
|
+
*/
|
|
7488
|
+
const paletteFallbacks = () => {
|
|
7489
|
+
const linda = characterPaletteToCssVars(DEFAULT_CHARACTER_PALETTE);
|
|
7490
|
+
return CHARACTER_CSS_VARS.map((name) => `\t--_lm-${name.slice(5)}: var(${name}, ${linda[name]});`).join("\n");
|
|
7491
|
+
};
|
|
7492
|
+
const AUTO_THEME = themeScopeSelectors(`${ROOT}[data-appearance="auto"]`);
|
|
7493
|
+
const reducedMotion = (root) => `
|
|
7494
|
+
${root},
|
|
7495
|
+
${root}::after,
|
|
7496
|
+
${root} *,
|
|
7497
|
+
${root} *::before,
|
|
7498
|
+
${root} *::after {
|
|
7097
7499
|
animation: none !important;
|
|
7500
|
+
transition: none !important;
|
|
7098
7501
|
}
|
|
7099
|
-
${root} .aurora-lm-
|
|
7100
|
-
|
|
7101
|
-
${root} .aurora-lm-level-halo {
|
|
7102
|
-
transform: none !important;
|
|
7103
|
-
}
|
|
7104
|
-
${root}.aurora-linda-mascot--listening .aurora-lm-level-rings,
|
|
7105
|
-
${root}.aurora-linda-mascot--talking .aurora-lm-level-rings {
|
|
7106
|
-
opacity: calc(0.55 + ${LEVEL} * 0.45);
|
|
7107
|
-
}
|
|
7108
|
-
${root}.aurora-linda-mascot--processing .aurora-lm-halo {
|
|
7109
|
-
animation: aurora-lm-glow 1.6s ease-in-out infinite !important;
|
|
7110
|
-
}
|
|
7111
|
-
${root}.aurora-linda-mascot--working .aurora-lm-halo {
|
|
7112
|
-
opacity: 1 !important;
|
|
7113
|
-
}
|
|
7114
|
-
${root}.aurora-linda-mascot--listening .aurora-lm-level-halo,
|
|
7115
|
-
${root}.aurora-linda-mascot--talking .aurora-lm-level-halo {
|
|
7116
|
-
opacity: calc(0.4 + ${LEVEL} * 0.6) !important;
|
|
7502
|
+
${root}.aurora-linda-mascot--loading .aurora-lm-load {
|
|
7503
|
+
opacity: 1;
|
|
7117
7504
|
}
|
|
7118
|
-
${root}.aurora-linda-mascot--
|
|
7119
|
-
|
|
7505
|
+
${root}.aurora-linda-mascot--loading .aurora-lm-body {
|
|
7506
|
+
opacity: 0;
|
|
7120
7507
|
}
|
|
7121
7508
|
`;
|
|
7122
|
-
|
|
7123
|
-
@media (prefers-reduced-motion: reduce) {${reducedMotionBody(root)}}
|
|
7124
|
-
${reducedMotionBody(`${root}[data-motion="reduce"]`)}
|
|
7125
|
-
`;
|
|
7509
|
+
/** Tiempo de respiración y grosor del aro por estado (`--breath` y `--rw` del lienzo). */
|
|
7126
7510
|
const LINDA_MASCOT_CSS = `
|
|
7127
|
-
|
|
7511
|
+
@property --aurora-lm-a {
|
|
7512
|
+
syntax: "<angle>";
|
|
7513
|
+
inherits: false;
|
|
7514
|
+
initial-value: 0deg;
|
|
7515
|
+
}
|
|
7516
|
+
|
|
7517
|
+
/*
|
|
7518
|
+
* La talla de la prop, en la capa \`base\` y con especificidad 0: cualquier clase del
|
|
7519
|
+
* consumidor la pisa, también las utilidades de Tailwind 4, que van en \`@layer utilities\`
|
|
7520
|
+
* y perderían contra una regla sin capa. Una capa con nombre propio no vale: inyectada
|
|
7521
|
+
* después de Tailwind quedaría detrás de \`utilities\` y volvería a ganar.
|
|
7522
|
+
*/
|
|
7523
|
+
@layer base {
|
|
7524
|
+
:where(${ROOT}) {
|
|
7525
|
+
width: var(--_lm-size, 72px);
|
|
7526
|
+
height: var(--_lm-size, 72px);
|
|
7527
|
+
}
|
|
7528
|
+
}
|
|
7529
|
+
|
|
7530
|
+
${ROOT} {
|
|
7531
|
+
${paletteFallbacks()}
|
|
7532
|
+
--_lm-s: 100cqmin;
|
|
7533
|
+
--_lm-rw: ${s(0.036)};
|
|
7534
|
+
--_lm-rb: var(--_lm-ring);
|
|
7535
|
+
--_lm-c1: var(--_lm-glow);
|
|
7536
|
+
--_lm-c2: var(--_lm-deep);
|
|
7537
|
+
--_lm-c3: var(--_lm-spark);
|
|
7538
|
+
--_lm-c4: var(--_lm-warm);
|
|
7539
|
+
--_lm-breath: 6s;
|
|
7540
|
+
--_lm-shadow-display: block;
|
|
7128
7541
|
${LINDA_MASCOT_LEVEL_VAR}: 0;
|
|
7129
|
-
|
|
7130
|
-
--lm-shadow: 1;
|
|
7131
|
-
--lm-rim: 0.85;
|
|
7132
|
-
--lm-sparkle: #F2B441;
|
|
7542
|
+
position: relative;
|
|
7133
7543
|
display: inline-block;
|
|
7134
7544
|
flex-shrink: 0;
|
|
7135
|
-
|
|
7545
|
+
container-type: size;
|
|
7136
7546
|
vertical-align: middle;
|
|
7547
|
+
overflow: visible;
|
|
7137
7548
|
}
|
|
7138
|
-
|
|
7139
|
-
|
|
7140
|
-
|
|
7141
|
-
|
|
7549
|
+
|
|
7550
|
+
/* Reflejo claro en el suelo, bajo la pompa. */
|
|
7551
|
+
${ROOT}::after {
|
|
7552
|
+
content: "";
|
|
7553
|
+
position: absolute;
|
|
7554
|
+
left: 28%;
|
|
7555
|
+
right: 28%;
|
|
7556
|
+
bottom: -14%;
|
|
7557
|
+
height: 6%;
|
|
7558
|
+
border-radius: 50%;
|
|
7559
|
+
background: radial-gradient(closest-side, ${white(0.7)}, ${mix("mint", 30)} 55%, transparent);
|
|
7560
|
+
filter: blur(${s(0.01)});
|
|
7561
|
+
pointer-events: none;
|
|
7142
7562
|
}
|
|
7143
|
-
|
|
7144
|
-
|
|
7145
|
-
|
|
7146
|
-
|
|
7147
|
-
|
|
7148
|
-
|
|
7149
|
-
--lm-halo: 0.95;
|
|
7150
|
-
--lm-shadow: 0;
|
|
7151
|
-
--lm-rim: 1;
|
|
7152
|
-
--lm-sparkle: #FFF1C9;
|
|
7563
|
+
|
|
7564
|
+
/* ── Estados: colores y ritmo ─────────────────────────────────────────────── */
|
|
7565
|
+
|
|
7566
|
+
.aurora-linda-mascot--ready,
|
|
7567
|
+
.aurora-linda-mascot--talking {
|
|
7568
|
+
--_lm-breath: 5s;
|
|
7153
7569
|
}
|
|
7154
|
-
|
|
7155
|
-
--
|
|
7156
|
-
--
|
|
7157
|
-
--lm-rim: 0.85;
|
|
7158
|
-
--lm-sparkle: #F2B441;
|
|
7570
|
+
.aurora-linda-mascot--listening {
|
|
7571
|
+
--_lm-breath: 6.5s;
|
|
7572
|
+
--_lm-rw: ${s(0.055)};
|
|
7159
7573
|
}
|
|
7160
|
-
|
|
7161
|
-
|
|
7162
|
-
|
|
7163
|
-
|
|
7164
|
-
|
|
7165
|
-
transform-box: view-box;
|
|
7166
|
-
transform-origin: 60px 61px;
|
|
7574
|
+
.aurora-linda-mascot--thinking {
|
|
7575
|
+
--_lm-rb: var(--_lm-thinking-ring);
|
|
7576
|
+
--_lm-c3: var(--_lm-teal);
|
|
7577
|
+
--_lm-c4: var(--_lm-deep);
|
|
7578
|
+
--_lm-breath: 5s;
|
|
7167
7579
|
}
|
|
7168
|
-
.aurora-
|
|
7169
|
-
|
|
7580
|
+
.aurora-linda-mascot--working {
|
|
7581
|
+
--_lm-breath: 1.8s;
|
|
7582
|
+
--_lm-rw: ${s(0.042)};
|
|
7170
7583
|
}
|
|
7171
|
-
.aurora-
|
|
7172
|
-
|
|
7173
|
-
|
|
7174
|
-
|
|
7584
|
+
.aurora-linda-mascot--alert {
|
|
7585
|
+
--_lm-rb: var(--_lm-alert-ring);
|
|
7586
|
+
--_lm-c1: var(--_lm-alert);
|
|
7587
|
+
--_lm-c2: var(--_lm-alert-deep);
|
|
7588
|
+
--_lm-c3: var(--_lm-alert-soft);
|
|
7589
|
+
--_lm-c4: var(--_lm-warm);
|
|
7590
|
+
--_lm-breath: 1.3s;
|
|
7175
7591
|
}
|
|
7176
7592
|
|
|
7177
|
-
/*
|
|
7178
|
-
|
|
7179
|
-
.
|
|
7180
|
-
|
|
7181
|
-
|
|
7593
|
+
/* ── Tema: en oscuro la sombra de contacto (tinta de la base) no se ve ───── */
|
|
7594
|
+
|
|
7595
|
+
${AUTO_THEME.dark},
|
|
7596
|
+
${ROOT}[data-appearance="dark"] {
|
|
7597
|
+
--_lm-shadow-display: none;
|
|
7182
7598
|
}
|
|
7183
|
-
.
|
|
7184
|
-
|
|
7185
|
-
transition: opacity 400ms ease;
|
|
7599
|
+
${AUTO_THEME.light} {
|
|
7600
|
+
--_lm-shadow-display: block;
|
|
7186
7601
|
}
|
|
7602
|
+
|
|
7603
|
+
/* ── Capas ────────────────────────────────────────────────────────────────── */
|
|
7604
|
+
|
|
7605
|
+
.aurora-lm-pulse,
|
|
7606
|
+
.aurora-lm-shadow,
|
|
7607
|
+
.aurora-lm-load,
|
|
7608
|
+
.aurora-lm-level,
|
|
7609
|
+
.aurora-lm-body,
|
|
7610
|
+
.aurora-lm-body > span,
|
|
7611
|
+
.aurora-lm-orbit,
|
|
7612
|
+
.aurora-lm-soap > span,
|
|
7613
|
+
.aurora-lm-headphones > span {
|
|
7614
|
+
position: absolute;
|
|
7615
|
+
box-sizing: border-box;
|
|
7616
|
+
}
|
|
7617
|
+
|
|
7618
|
+
/* Ondas: solo al escuchar y en aviso. */
|
|
7619
|
+
.aurora-lm-pulse {
|
|
7620
|
+
inset: 4%;
|
|
7621
|
+
border-radius: 50%;
|
|
7622
|
+
border: ${s(0.01)} solid var(--_lm-c1);
|
|
7623
|
+
opacity: 0;
|
|
7624
|
+
pointer-events: none;
|
|
7625
|
+
}
|
|
7626
|
+
|
|
7187
7627
|
.aurora-lm-shadow {
|
|
7188
|
-
|
|
7628
|
+
display: var(--_lm-shadow-display);
|
|
7629
|
+
left: 18%;
|
|
7630
|
+
right: 18%;
|
|
7631
|
+
bottom: -12%;
|
|
7632
|
+
height: 9%;
|
|
7633
|
+
border-radius: 50%;
|
|
7634
|
+
background: radial-gradient(closest-side, ${mix("core", 28)}, ${mix("core", 8)} 60%, transparent);
|
|
7635
|
+
filter: blur(${s(0.012)});
|
|
7636
|
+
animation: aurora-lm-shadow var(--_lm-breath) ease-in-out infinite;
|
|
7637
|
+
}
|
|
7638
|
+
|
|
7639
|
+
/* Cargando: cuadrícula de 9 puntos, oculta en el resto de estados. */
|
|
7640
|
+
.aurora-lm-load {
|
|
7641
|
+
display: none;
|
|
7642
|
+
left: 50%;
|
|
7643
|
+
top: 44%;
|
|
7644
|
+
width: 52%;
|
|
7645
|
+
aspect-ratio: 1;
|
|
7646
|
+
translate: -50% -50%;
|
|
7647
|
+
grid-template-columns: repeat(3, 1fr);
|
|
7648
|
+
grid-template-rows: repeat(3, 1fr);
|
|
7649
|
+
place-items: center;
|
|
7650
|
+
opacity: 0;
|
|
7651
|
+
z-index: 5;
|
|
7652
|
+
}
|
|
7653
|
+
.aurora-lm-dot {
|
|
7654
|
+
--_lm-dot: var(--_lm-c2);
|
|
7655
|
+
display: block;
|
|
7656
|
+
width: 58%;
|
|
7657
|
+
aspect-ratio: 1;
|
|
7658
|
+
border-radius: 50%;
|
|
7659
|
+
background: var(--_lm-dot);
|
|
7660
|
+
box-shadow: 0 0 ${s(0.03)} var(--_lm-dot), inset 0 ${s(-6e-3)} ${s(0.01)} ${black(0.12)}, inset 0 ${s(0.006)} ${s(0.008)} ${white(0.6)};
|
|
7661
|
+
opacity: 0.25;
|
|
7662
|
+
}
|
|
7663
|
+
.aurora-lm-dot--1 { --_lm-dot: var(--_lm-c2); animation-delay: 1.6s; }
|
|
7664
|
+
.aurora-lm-dot--2 { --_lm-dot: var(--_lm-c1); animation-delay: 1.75s; }
|
|
7665
|
+
.aurora-lm-dot--3 { --_lm-dot: var(--_lm-c3); animation-delay: 1.9s; }
|
|
7666
|
+
.aurora-lm-dot--6 { --_lm-dot: var(--_lm-c4); animation-delay: 2.05s; }
|
|
7667
|
+
.aurora-lm-dot--9 { --_lm-dot: var(--_lm-c2); animation-delay: 2.2s; }
|
|
7668
|
+
.aurora-lm-dot--8 { --_lm-dot: var(--_lm-c1); animation-delay: 2.35s; }
|
|
7669
|
+
.aurora-lm-dot--7 { --_lm-dot: var(--_lm-c3); animation-delay: 2.5s; }
|
|
7670
|
+
.aurora-lm-dot--4 { --_lm-dot: var(--_lm-c4); animation-delay: 2.65s; }
|
|
7671
|
+
|
|
7672
|
+
/* Envoltorio que solo escala con la voz: separado de las animaciones del cuerpo. */
|
|
7673
|
+
.aurora-lm-level {
|
|
7674
|
+
inset: 0;
|
|
7675
|
+
transition: scale 140ms cubic-bezier(0.22, 0.7, 0.3, 1);
|
|
7676
|
+
}
|
|
7677
|
+
|
|
7678
|
+
.aurora-lm-body {
|
|
7679
|
+
inset: 0;
|
|
7680
|
+
animation: aurora-lm-float var(--_lm-breath) ease-in-out infinite;
|
|
7681
|
+
}
|
|
7682
|
+
|
|
7683
|
+
/* Aro: borde cónico que gira el color; su resplandor, el mismo aro desenfocado. */
|
|
7684
|
+
.aurora-lm-rimglow {
|
|
7685
|
+
inset: 0;
|
|
7686
|
+
filter: blur(${s(0.028)}) saturate(1.8) brightness(1.45);
|
|
7687
|
+
}
|
|
7688
|
+
.aurora-lm-rim-glow,
|
|
7689
|
+
.aurora-lm-rim {
|
|
7690
|
+
border-style: solid;
|
|
7691
|
+
border-color: transparent;
|
|
7692
|
+
background: conic-gradient(from var(--aurora-lm-a), var(--_lm-rb)) border-box;
|
|
7693
|
+
${BORDER_ONLY}
|
|
7694
|
+
animation: aurora-lm-hue 8s linear infinite, aurora-lm-squish var(--_lm-breath) ease-in-out infinite;
|
|
7695
|
+
}
|
|
7696
|
+
.aurora-lm-rim-glow {
|
|
7697
|
+
position: absolute;
|
|
7698
|
+
box-sizing: border-box;
|
|
7699
|
+
inset: 10.5% 10.5% 20.5% 18.5%;
|
|
7700
|
+
border-radius: ${EGG};
|
|
7701
|
+
border-width: calc(var(--_lm-rw) * 1.4) calc(var(--_lm-rw) * 1.3) calc(var(--_lm-rw) * 2) calc(var(--_lm-rw) * 1.9);
|
|
7189
7702
|
}
|
|
7190
7703
|
.aurora-lm-rim {
|
|
7191
|
-
|
|
7704
|
+
inset: 12% 12% 22% 20%;
|
|
7705
|
+
border-radius: ${EGG};
|
|
7706
|
+
border-width: calc(var(--_lm-rw) * 0.7) calc(var(--_lm-rw) * 0.6) calc(var(--_lm-rw) * 1.3) calc(var(--_lm-rw) * 1.25);
|
|
7707
|
+
filter: blur(${s(0.0015)}) saturate(1.9) brightness(1.35);
|
|
7708
|
+
}
|
|
7709
|
+
.aurora-lm-rimline {
|
|
7710
|
+
inset: 12% 12% 22% 20%;
|
|
7711
|
+
border-radius: ${EGG};
|
|
7712
|
+
box-shadow: 0 0 0 ${s(0.004)} ${mix("outline", 95)}, 0 0 0 ${s(0.007)} ${mix("outline", 40)};
|
|
7713
|
+
pointer-events: none;
|
|
7714
|
+
animation: aurora-lm-squish var(--_lm-breath) ease-in-out infinite;
|
|
7715
|
+
}
|
|
7716
|
+
|
|
7717
|
+
/* Núcleo oscuro con su reflejo. */
|
|
7718
|
+
.aurora-lm-core {
|
|
7719
|
+
inset: 12% 12% 22% 20%;
|
|
7720
|
+
border-radius: ${EGG};
|
|
7721
|
+
background: radial-gradient(ellipse at 30% 80%, ${mix("deep", 28)}, transparent 45%), radial-gradient(ellipse at 80% 60%, ${mix("glow", 12)}, transparent 40%), var(--_lm-core);
|
|
7722
|
+
box-shadow: inset 0 0 ${s(0.03)} ${mix("glow", 25)};
|
|
7723
|
+
scale: 0.975;
|
|
7724
|
+
animation: aurora-lm-squish var(--_lm-breath) ease-in-out infinite;
|
|
7725
|
+
}
|
|
7726
|
+
.aurora-lm-core::before {
|
|
7727
|
+
content: "";
|
|
7728
|
+
position: absolute;
|
|
7729
|
+
right: 10%;
|
|
7730
|
+
top: 7%;
|
|
7731
|
+
width: 46%;
|
|
7732
|
+
height: 26%;
|
|
7733
|
+
border-radius: 50%;
|
|
7734
|
+
background: linear-gradient(200deg, ${white(0.55)}, ${white(0)} 75%);
|
|
7735
|
+
transform: rotate(28deg);
|
|
7736
|
+
filter: blur(${s(0.008)});
|
|
7737
|
+
z-index: 1;
|
|
7738
|
+
}
|
|
7739
|
+
|
|
7740
|
+
/* Órbitas de pensar: tres luces girando dentro del núcleo. */
|
|
7741
|
+
.aurora-lm-orbits {
|
|
7742
|
+
inset: 22% 18% 30% 26%;
|
|
7743
|
+
opacity: 0;
|
|
7744
|
+
transition: opacity 0.6s;
|
|
7192
7745
|
}
|
|
7193
|
-
|
|
7194
|
-
/*
|
|
7195
|
-
* Anillos. El círculo gira dentro de su grupo aplastado: la elipse no cambia de forma y
|
|
7196
|
-
* lo que recorre el trazo es el color, como un anillo que gira en profundidad.
|
|
7197
|
-
* \`--lm-spin-duration\` y \`--lm-spin-direction\` llegan por anillo desde el marcado.
|
|
7198
|
-
*/
|
|
7199
|
-
.aurora-lm-spin {
|
|
7200
|
-
transform-box: view-box;
|
|
7201
|
-
transform-origin: 0 0;
|
|
7202
|
-
animation: aurora-lm-spin var(--lm-spin-duration, 24s) linear infinite
|
|
7203
|
-
var(--lm-spin-direction, normal);
|
|
7204
|
-
}
|
|
7205
|
-
/* Segundo giro encadenado: parado salvo en working, donde dobla la velocidad sin saltos
|
|
7206
|
-
(pausar conserva el ángulo; cambiar la duración lo haría saltar). */
|
|
7207
|
-
.aurora-lm-boost {
|
|
7208
|
-
animation-play-state: paused;
|
|
7209
|
-
}
|
|
7210
|
-
/* Cometa del anillo principal: orbita siempre, se ve solo al pensar o trabajar. */
|
|
7211
7746
|
.aurora-lm-orbit {
|
|
7212
|
-
|
|
7747
|
+
inset: 0;
|
|
7213
7748
|
}
|
|
7214
|
-
.aurora-lm-
|
|
7215
|
-
|
|
7216
|
-
|
|
7217
|
-
|
|
7749
|
+
.aurora-lm-orbit::before {
|
|
7750
|
+
content: "";
|
|
7751
|
+
position: absolute;
|
|
7752
|
+
top: 0;
|
|
7753
|
+
left: 50%;
|
|
7754
|
+
width: ${s(0.034)};
|
|
7755
|
+
height: ${s(0.034)};
|
|
7756
|
+
margin-left: ${s(-0.017)};
|
|
7757
|
+
border-radius: 50%;
|
|
7758
|
+
background: var(--_lm-light);
|
|
7759
|
+
box-shadow: 0 0 ${s(0.04)} var(--_lm-c1);
|
|
7760
|
+
}
|
|
7761
|
+
.aurora-lm-orbit--2 {
|
|
7762
|
+
inset: 14%;
|
|
7763
|
+
}
|
|
7764
|
+
.aurora-lm-orbit--2::before {
|
|
7765
|
+
background: var(--_lm-c3);
|
|
7766
|
+
}
|
|
7767
|
+
.aurora-lm-orbit--3 {
|
|
7768
|
+
inset: -10%;
|
|
7769
|
+
}
|
|
7770
|
+
.aurora-lm-orbit--3::before {
|
|
7771
|
+
background: var(--_lm-c4);
|
|
7772
|
+
width: ${s(0.024)};
|
|
7773
|
+
height: ${s(0.024)};
|
|
7218
7774
|
}
|
|
7219
7775
|
|
|
7220
|
-
/* Ojos:
|
|
7776
|
+
/* Ojos: dos cápsulas de luz que parpadean. */
|
|
7221
7777
|
.aurora-lm-eyes {
|
|
7222
|
-
|
|
7223
|
-
|
|
7224
|
-
|
|
7778
|
+
left: 54%;
|
|
7779
|
+
top: 50%;
|
|
7780
|
+
width: 42%;
|
|
7781
|
+
height: 22%;
|
|
7782
|
+
transform: translate(-50%, -50%);
|
|
7783
|
+
display: flex;
|
|
7784
|
+
justify-content: space-between;
|
|
7785
|
+
align-items: center;
|
|
7786
|
+
transition: transform 0.6s ease;
|
|
7225
7787
|
}
|
|
7226
|
-
|
|
7227
|
-
|
|
7228
|
-
|
|
7229
|
-
|
|
7230
|
-
|
|
7231
|
-
|
|
7232
|
-
|
|
7233
|
-
|
|
7788
|
+
.aurora-lm-eye {
|
|
7789
|
+
display: block;
|
|
7790
|
+
box-sizing: border-box;
|
|
7791
|
+
width: 24%;
|
|
7792
|
+
height: 60%;
|
|
7793
|
+
border-radius: 999px;
|
|
7794
|
+
background: linear-gradient(180deg, var(--_lm-light) 0%, var(--_lm-light) 55%, var(--_lm-mint) 100%);
|
|
7795
|
+
box-shadow: 0 0 ${s(0.025)} var(--_lm-light), 0 0 ${s(0.08)} var(--_lm-glow);
|
|
7796
|
+
animation: aurora-lm-blink 5s infinite;
|
|
7797
|
+
transition: scale 0.5s ease, rotate 0.5s ease;
|
|
7798
|
+
}
|
|
7799
|
+
|
|
7800
|
+
/* Gafas de trabajar: ojo de gato en línea, del color de los ojos. */
|
|
7801
|
+
.aurora-lm-glasses {
|
|
7802
|
+
position: absolute;
|
|
7803
|
+
left: -16%;
|
|
7804
|
+
top: -12%;
|
|
7805
|
+
width: 132%;
|
|
7806
|
+
height: 124%;
|
|
7807
|
+
overflow: visible;
|
|
7808
|
+
filter: drop-shadow(0 0 ${s(0.006)} var(--_lm-light)) drop-shadow(0 0 ${s(0.016)} ${mix("light", 60)});
|
|
7809
|
+
}
|
|
7810
|
+
.aurora-lm-glasses g {
|
|
7811
|
+
fill: none;
|
|
7812
|
+
stroke: var(--_lm-light);
|
|
7813
|
+
stroke-width: 7;
|
|
7814
|
+
stroke-linejoin: round;
|
|
7815
|
+
stroke-linecap: round;
|
|
7816
|
+
}
|
|
7817
|
+
|
|
7818
|
+
/* Pompa de jabón: la burbuja que envuelve al personaje. */
|
|
7819
|
+
.aurora-lm-bubble {
|
|
7820
|
+
inset: -3% -2% -1% -4%;
|
|
7821
|
+
overflow: hidden;
|
|
7822
|
+
border-radius: ${BUBBLE_SHAPE};
|
|
7823
|
+
background: radial-gradient(circle at 38% 32%, ${white(0.12)} 0%, transparent 45%), radial-gradient(circle at 50% 50%, transparent 66%, ${mix("core", 4)} 78%, ${mix("core", 10)} 87%, ${white(0.28)} 93%, ${white(0.4)} 96%, ${white(0.12)} 99%, transparent 100%);
|
|
7824
|
+
box-shadow: inset ${s(-0.03)} ${s(-0.04)} ${s(0.07)} ${mix("core", 14)}, inset ${s(0.02)} ${s(0.025)} ${s(0.06)} ${white(0.4)}, 0 0 ${s(0.05)} ${white(0.35)}, 0 0 ${s(0.12)} ${mix("mint", 30)};
|
|
7825
|
+
filter: blur(${s(0.006)});
|
|
7826
|
+
animation: aurora-lm-jabon 11s ${SOFT_EASE} infinite, aurora-lm-breathe 7.3s ${SOFT_EASE} infinite, aurora-lm-drift 16s linear infinite;
|
|
7827
|
+
}
|
|
7828
|
+
.aurora-lm-bubble::before {
|
|
7829
|
+
content: "";
|
|
7830
|
+
position: absolute;
|
|
7831
|
+
inset: 0;
|
|
7832
|
+
border-radius: inherit;
|
|
7833
|
+
background: conic-gradient(from var(--aurora-lm-a), var(--_lm-film-1) 0deg, var(--_lm-film-2) 80deg, var(--_lm-film-3) 130deg, var(--_lm-film-4) 185deg, var(--_lm-film-5) 225deg, var(--_lm-film-1) 290deg, var(--_lm-film-1) 360deg);
|
|
7834
|
+
-webkit-mask: radial-gradient(closest-side, transparent 52%, ${black(0.6)} 78%, black 100%);
|
|
7835
|
+
mask: radial-gradient(closest-side, transparent 52%, ${black(0.6)} 78%, black 100%);
|
|
7836
|
+
opacity: 0.4;
|
|
7837
|
+
animation: aurora-lm-hue 36s linear infinite;
|
|
7838
|
+
}
|
|
7839
|
+
|
|
7840
|
+
/* Reflejos y película de la pompa. */
|
|
7841
|
+
.aurora-lm-soap {
|
|
7842
|
+
left: -4%;
|
|
7843
|
+
top: -3%;
|
|
7844
|
+
right: -2%;
|
|
7845
|
+
bottom: -1%;
|
|
7846
|
+
overflow: hidden;
|
|
7847
|
+
border-radius: ${BUBBLE_SHAPE};
|
|
7848
|
+
-webkit-mask: radial-gradient(closest-side, black 92%, transparent 100%);
|
|
7849
|
+
mask: radial-gradient(closest-side, black 92%, transparent 100%);
|
|
7850
|
+
animation: aurora-lm-jabon 11s ${SOFT_EASE} infinite, aurora-lm-breathe 7.3s ${SOFT_EASE} infinite, aurora-lm-drift 40s linear infinite;
|
|
7851
|
+
}
|
|
7852
|
+
.aurora-lm-soap > span:nth-child(1) {
|
|
7853
|
+
left: 17%;
|
|
7854
|
+
right: 13%;
|
|
7855
|
+
top: 1.2%;
|
|
7856
|
+
height: 34%;
|
|
7857
|
+
border-radius: 50% 50% 40% 46% / 80% 80% 20% 28%;
|
|
7858
|
+
background: radial-gradient(ellipse 120% 150% at 50% 135%, ${mix("deep", 0)} 52%, ${mix("deep", 55)} 60%, ${mix("glow", 80)} 68%, ${mix("spark", 80)} 76%, ${mix("film-2", 85)} 83%, ${mix("warm", 90)} 90%, ${white(0.95)} 97%);
|
|
7859
|
+
mix-blend-mode: screen;
|
|
7860
|
+
opacity: 0.45;
|
|
7861
|
+
filter: blur(${s(0.008)});
|
|
7862
|
+
}
|
|
7863
|
+
.aurora-lm-soap > span:nth-child(2) {
|
|
7864
|
+
left: 18%;
|
|
7865
|
+
width: 46%;
|
|
7866
|
+
bottom: 6%;
|
|
7867
|
+
height: 26%;
|
|
7868
|
+
border-radius: 45% 55% 50% 50% / 55% 45% 55% 45%;
|
|
7869
|
+
background: radial-gradient(ellipse 130% 110% at 50% -10%, ${mix("glow", 0)} 40%, ${mix("glow", 60)} 55%, ${mix("deep", 55)} 70%, ${mix("warm", 65)} 85%, ${white(0.35)} 100%);
|
|
7870
|
+
mix-blend-mode: screen;
|
|
7871
|
+
opacity: 0.38;
|
|
7872
|
+
filter: blur(${s(0.014)});
|
|
7873
|
+
}
|
|
7874
|
+
.aurora-lm-soap > span:nth-child(3) {
|
|
7875
|
+
left: 42%;
|
|
7876
|
+
right: 12%;
|
|
7877
|
+
bottom: 8%;
|
|
7878
|
+
height: 24%;
|
|
7879
|
+
border-radius: 55% 45% 45% 55% / 50% 60% 40% 50%;
|
|
7880
|
+
background: radial-gradient(ellipse 120% 110% at 40% -5%, ${mix("glow", 0)} 38%, ${mix("glow", 70)} 52%, ${mix("warm", 70)} 72%, ${mix("warm", 60)} 88%, ${white(0.3)} 100%);
|
|
7881
|
+
mix-blend-mode: screen;
|
|
7882
|
+
opacity: 0.38;
|
|
7883
|
+
filter: blur(${s(0.014)});
|
|
7884
|
+
}
|
|
7885
|
+
.aurora-lm-soap > span:nth-child(4) {
|
|
7886
|
+
inset: 0;
|
|
7887
|
+
border-radius: inherit;
|
|
7888
|
+
box-shadow: inset ${s(0.015)} ${s(-0.02)} ${s(0.02)} ${mix("core", 18)}, inset ${s(-0.01)} ${s(0.01)} ${s(0.03)} ${white(0.35)};
|
|
7889
|
+
}
|
|
7890
|
+
.aurora-lm-soap > span:nth-child(5) {
|
|
7891
|
+
left: 16%;
|
|
7892
|
+
top: 15%;
|
|
7893
|
+
width: 15%;
|
|
7894
|
+
height: 10%;
|
|
7895
|
+
border-radius: 40%;
|
|
7896
|
+
background: linear-gradient(160deg, ${white(0.95)}, ${white(0.35)});
|
|
7897
|
+
rotate: -35deg;
|
|
7898
|
+
filter: blur(${s(0.004)});
|
|
7899
|
+
}
|
|
7900
|
+
.aurora-lm-soap > span:nth-child(6) {
|
|
7901
|
+
left: 14%;
|
|
7902
|
+
top: 28%;
|
|
7903
|
+
width: 6%;
|
|
7904
|
+
height: 4%;
|
|
7905
|
+
border-radius: 50%;
|
|
7906
|
+
background: ${white(0.9)};
|
|
7907
|
+
rotate: -35deg;
|
|
7908
|
+
filter: blur(${s(0.003)});
|
|
7909
|
+
}
|
|
7910
|
+
.aurora-lm-soap > span:nth-child(7) {
|
|
7911
|
+
right: 14%;
|
|
7912
|
+
top: 12%;
|
|
7913
|
+
width: 5%;
|
|
7914
|
+
height: 5%;
|
|
7915
|
+
border-radius: 50%;
|
|
7916
|
+
background: radial-gradient(closest-side, ${white(1)}, ${white(0)});
|
|
7917
|
+
filter: blur(${s(0.002)});
|
|
7918
|
+
}
|
|
7919
|
+
.aurora-lm-soap > span:nth-child(8) {
|
|
7920
|
+
inset: 1.2%;
|
|
7921
|
+
border-radius: inherit;
|
|
7922
|
+
border: ${s(0.012)} solid transparent;
|
|
7923
|
+
border-left-color: ${white(0.85)};
|
|
7924
|
+
border-bottom-color: ${white(0.55)};
|
|
7925
|
+
rotate: 20deg;
|
|
7926
|
+
filter: blur(${s(0.012)});
|
|
7927
|
+
opacity: 0.8;
|
|
7928
|
+
}
|
|
7929
|
+
.aurora-lm-soap > span:nth-child(9) {
|
|
7930
|
+
inset: 2.5%;
|
|
7931
|
+
border-radius: inherit;
|
|
7932
|
+
border: ${s(0.008)} solid transparent;
|
|
7933
|
+
border-right-color: ${white(0.7)};
|
|
7934
|
+
border-top-color: ${white(0.3)};
|
|
7935
|
+
rotate: -15deg;
|
|
7936
|
+
filter: blur(${s(0.01)});
|
|
7937
|
+
opacity: 0.7;
|
|
7938
|
+
}
|
|
7939
|
+
.aurora-lm-soap > span:nth-child(10) {
|
|
7940
|
+
left: 24%;
|
|
7941
|
+
right: 18%;
|
|
7942
|
+
top: 1.4%;
|
|
7943
|
+
height: 6%;
|
|
7944
|
+
border-radius: 50% 50% 0 0 / 100% 100% 0 0;
|
|
7945
|
+
border-top: ${s(0.01)} solid ${white(0.95)};
|
|
7946
|
+
filter: blur(${s(0.006)});
|
|
7947
|
+
}
|
|
7948
|
+
.aurora-lm-soap > span:nth-child(11) {
|
|
7949
|
+
right: 20%;
|
|
7950
|
+
bottom: 10%;
|
|
7951
|
+
width: 8%;
|
|
7952
|
+
height: 3%;
|
|
7953
|
+
border-radius: 50%;
|
|
7954
|
+
background: ${white(0.85)};
|
|
7955
|
+
rotate: -20deg;
|
|
7956
|
+
filter: blur(${s(0.004)});
|
|
7957
|
+
}
|
|
7958
|
+
.aurora-lm-soap > span:nth-child(12) {
|
|
7959
|
+
left: 34%;
|
|
7960
|
+
right: 26%;
|
|
7961
|
+
bottom: 3.5%;
|
|
7962
|
+
height: 9%;
|
|
7963
|
+
border-radius: 50%;
|
|
7964
|
+
background: radial-gradient(closest-side, ${white(0.9)}, ${mix("mint", 55)} 45%, transparent);
|
|
7965
|
+
filter: blur(${s(0.008)});
|
|
7966
|
+
}
|
|
7967
|
+
.aurora-lm-soap > span:nth-child(13) {
|
|
7968
|
+
inset: 0;
|
|
7969
|
+
border-radius: inherit;
|
|
7970
|
+
background: radial-gradient(circle at 70% 78%, ${mix("core", 12)}, transparent 38%);
|
|
7971
|
+
}
|
|
7972
|
+
|
|
7973
|
+
/* Auriculares de escuchar. */
|
|
7974
|
+
.aurora-lm-headphones {
|
|
7975
|
+
inset: 9% 9% 19% 17%;
|
|
7976
|
+
rotate: -6deg;
|
|
7977
|
+
transform-origin: 50% 55%;
|
|
7978
|
+
}
|
|
7979
|
+
.aurora-lm-headphones-arc {
|
|
7980
|
+
left: 4%;
|
|
7981
|
+
right: 4%;
|
|
7982
|
+
top: -6%;
|
|
7983
|
+
height: 58%;
|
|
7984
|
+
border: ${s(0.03)} solid var(--_lm-core);
|
|
7985
|
+
border-bottom: 0;
|
|
7986
|
+
border-radius: 50% 50% 0 0 / 100% 100% 0 0;
|
|
7987
|
+
filter: drop-shadow(0 ${s(0.01)} ${s(0.015)} ${mix("core", 25)});
|
|
7988
|
+
}
|
|
7989
|
+
.aurora-lm-headphones-cup {
|
|
7990
|
+
top: 32%;
|
|
7991
|
+
width: 20%;
|
|
7992
|
+
height: 36%;
|
|
7993
|
+
border-radius: 50% 50% 46% 46% / 50% 50% 50% 50%;
|
|
7994
|
+
background: radial-gradient(circle at 35% 28%, var(--_lm-teal), color-mix(in srgb, var(--_lm-teal) 45%, var(--_lm-core)) 50%, var(--_lm-core) 100%);
|
|
7995
|
+
box-shadow: inset 0 0 0 ${s(0.018)} var(--_lm-glow), 0 ${s(0.02)} ${s(0.03)} ${mix("core", 30)};
|
|
7996
|
+
}
|
|
7997
|
+
.aurora-lm-headphones-cup--left {
|
|
7998
|
+
left: -5%;
|
|
7999
|
+
rotate: 10deg;
|
|
8000
|
+
}
|
|
8001
|
+
.aurora-lm-headphones-cup--right {
|
|
8002
|
+
right: -5%;
|
|
8003
|
+
rotate: -10deg;
|
|
8004
|
+
}
|
|
8005
|
+
|
|
8006
|
+
/* ── Estados: movimiento, ojos y accesorios ───────────────────────────────── */
|
|
8007
|
+
|
|
8008
|
+
/* Lista (reposo) y hablando: flota sereno y una luz blanca recorre el aro. */
|
|
8009
|
+
.aurora-linda-mascot--ready .aurora-lm-body,
|
|
8010
|
+
.aurora-linda-mascot--talking .aurora-lm-body {
|
|
8011
|
+
animation: aurora-lm-ready 4s ease-in-out infinite;
|
|
8012
|
+
}
|
|
8013
|
+
.aurora-linda-mascot--ready .aurora-lm-rim,
|
|
8014
|
+
.aurora-linda-mascot--talking .aurora-lm-rim {
|
|
8015
|
+
background: conic-gradient(from var(--aurora-lm-a), transparent 0deg 150deg, ${white(0.6)} 270deg, ${white(1)} 320deg, ${white(1)} 355deg, transparent 360deg) border-box, conic-gradient(from var(--aurora-lm-a), var(--_lm-rb)) border-box;
|
|
8016
|
+
animation: aurora-lm-hue 2.6s linear infinite;
|
|
8017
|
+
}
|
|
8018
|
+
.aurora-linda-mascot--ready .aurora-lm-rim-glow,
|
|
8019
|
+
.aurora-linda-mascot--talking .aurora-lm-rim-glow {
|
|
8020
|
+
background: conic-gradient(from var(--aurora-lm-a), transparent 0deg 200deg, ${mix("glow", 90)} 300deg, ${white(1)} 350deg, transparent 360deg) border-box, conic-gradient(from var(--aurora-lm-a), var(--_lm-rb)) border-box;
|
|
8021
|
+
animation: aurora-lm-hue 2.6s linear infinite;
|
|
8022
|
+
}
|
|
8023
|
+
.aurora-linda-mascot--ready .aurora-lm-eye,
|
|
8024
|
+
.aurora-linda-mascot--talking .aurora-lm-eye {
|
|
8025
|
+
scale: 1.15 1;
|
|
8026
|
+
-webkit-mask: radial-gradient(ellipse 66% 74% at 50% 104%, transparent 98%, black 100%);
|
|
8027
|
+
mask: radial-gradient(ellipse 66% 74% at 50% 104%, transparent 98%, black 100%);
|
|
8028
|
+
}
|
|
8029
|
+
.aurora-linda-mascot--talking .aurora-lm-level {
|
|
8030
|
+
scale: calc(1 + ${LEVEL} * 0.07);
|
|
8031
|
+
}
|
|
8032
|
+
|
|
8033
|
+
/* Escuchando: auriculares, asiente y lanza ondas en azul y verde. */
|
|
8034
|
+
.aurora-linda-mascot--listening .aurora-lm-body {
|
|
8035
|
+
animation: aurora-lm-float var(--_lm-breath) ease-in-out infinite, aurora-lm-nod 2.8s ease-in-out infinite;
|
|
8036
|
+
}
|
|
8037
|
+
.aurora-linda-mascot--listening .aurora-lm-level {
|
|
8038
|
+
scale: calc(1 + ${LEVEL} * 0.05);
|
|
8039
|
+
}
|
|
8040
|
+
.aurora-linda-mascot--listening .aurora-lm-rim,
|
|
8041
|
+
.aurora-linda-mascot--listening .aurora-lm-rim-glow {
|
|
8042
|
+
animation: aurora-lm-hue 3.5s linear infinite;
|
|
8043
|
+
}
|
|
8044
|
+
.aurora-linda-mascot--listening .aurora-lm-eyes {
|
|
8045
|
+
transform: translate(-50%, -50%) rotate(-7deg);
|
|
8046
|
+
animation: aurora-lm-nod-eyes 2.8s ease-in-out infinite;
|
|
8047
|
+
}
|
|
8048
|
+
.aurora-linda-mascot--listening .aurora-lm-eye {
|
|
8049
|
+
scale: 1.12 1.22;
|
|
8050
|
+
}
|
|
8051
|
+
.aurora-linda-mascot--listening .aurora-lm-pulse {
|
|
8052
|
+
border-color: var(--_lm-deep);
|
|
8053
|
+
box-shadow: 0 0 ${s(0.03)} ${mix("deep", 45)}, inset 0 0 ${s(0.02)} ${mix("glow", 35)};
|
|
8054
|
+
filter: blur(${s(0.002)});
|
|
8055
|
+
animation: aurora-lm-listen-wave 2.8s cubic-bezier(0.22, 0.61, 0.36, 1) 0.12s infinite;
|
|
8056
|
+
}
|
|
8057
|
+
.aurora-linda-mascot--listening .aurora-lm-pulse--2 {
|
|
8058
|
+
border-color: var(--_lm-spark);
|
|
8059
|
+
box-shadow: 0 0 ${s(0.03)} ${mix("spark", 45)}, inset 0 0 ${s(0.02)} ${mix("mint", 40)};
|
|
8060
|
+
animation-delay: 0.58s;
|
|
8061
|
+
}
|
|
8062
|
+
.aurora-linda-mascot--listening .aurora-lm-bubble {
|
|
8063
|
+
box-shadow: inset ${s(-0.03)} ${s(-0.04)} ${s(0.07)} ${mix("core", 14)}, inset 0 0 ${s(0.06)} ${mix("deep", 35)}, 0 0 ${s(0.06)} ${mix("deep", 35)}, 0 0 ${s(0.14)} ${mix("spark", 20)};
|
|
7234
8064
|
}
|
|
7235
8065
|
|
|
7236
|
-
/*
|
|
7237
|
-
|
|
7238
|
-
|
|
7239
|
-
|
|
7240
|
-
.aurora-linda-mascot--processing .aurora-lm-orbit {
|
|
7241
|
-
animation-play-state: running;
|
|
8066
|
+
/* Pensando: el aro se enfría, mira arriba de un lado a otro y entrecierra los ojos. */
|
|
8067
|
+
.aurora-linda-mascot--thinking .aurora-lm-body {
|
|
8068
|
+
animation: aurora-lm-float var(--_lm-breath) ease-in-out infinite, aurora-lm-tilt 9s ease-in-out infinite;
|
|
7242
8069
|
}
|
|
7243
|
-
.aurora-linda-mascot--
|
|
8070
|
+
.aurora-linda-mascot--thinking .aurora-lm-orbits {
|
|
7244
8071
|
opacity: 1;
|
|
7245
8072
|
}
|
|
7246
|
-
|
|
7247
|
-
|
|
8073
|
+
/* Solo aquí giran: invisibles en el resto de estados, no gastan animación. */
|
|
8074
|
+
.aurora-linda-mascot--thinking .aurora-lm-orbit {
|
|
8075
|
+
animation: aurora-lm-spin 1.9s linear infinite;
|
|
8076
|
+
}
|
|
8077
|
+
.aurora-linda-mascot--thinking .aurora-lm-orbit--2 {
|
|
8078
|
+
animation-duration: 2.6s;
|
|
8079
|
+
animation-direction: reverse;
|
|
8080
|
+
}
|
|
8081
|
+
.aurora-linda-mascot--thinking .aurora-lm-orbit--3 {
|
|
8082
|
+
animation-duration: 3.8s;
|
|
8083
|
+
}
|
|
8084
|
+
.aurora-linda-mascot--thinking .aurora-lm-eyes {
|
|
8085
|
+
transform: translate(-50%, -58%);
|
|
8086
|
+
animation: aurora-lm-think 5s ease-in-out infinite;
|
|
8087
|
+
}
|
|
8088
|
+
.aurora-linda-mascot--thinking .aurora-lm-eye {
|
|
8089
|
+
animation: aurora-lm-squint 3.6s ease-in-out infinite;
|
|
7248
8090
|
}
|
|
7249
8091
|
|
|
7250
|
-
.
|
|
7251
|
-
.aurora-linda-mascot--working .aurora-lm-
|
|
7252
|
-
animation-
|
|
8092
|
+
/* Trabajando: gafas, vibra y los ojos recorren de lado a lado. */
|
|
8093
|
+
.aurora-linda-mascot--working .aurora-lm-body {
|
|
8094
|
+
animation: aurora-lm-buzz 0.45s linear infinite;
|
|
7253
8095
|
}
|
|
7254
|
-
.aurora-linda-mascot--working .aurora-lm-
|
|
7255
|
-
|
|
8096
|
+
.aurora-linda-mascot--working .aurora-lm-core {
|
|
8097
|
+
animation: aurora-lm-squish 1.8s ease-in-out infinite, aurora-lm-flicker 0.9s ease-in-out infinite;
|
|
8098
|
+
}
|
|
8099
|
+
.aurora-linda-mascot--working .aurora-lm-eyes {
|
|
8100
|
+
transform: translate(-50%, -44%);
|
|
8101
|
+
justify-content: space-around;
|
|
8102
|
+
animation: aurora-lm-scan 1.4s ease-in-out infinite;
|
|
8103
|
+
}
|
|
8104
|
+
.aurora-linda-mascot--working .aurora-lm-eye {
|
|
8105
|
+
scale: 0.64 0.52;
|
|
7256
8106
|
}
|
|
7257
8107
|
|
|
7258
|
-
|
|
7259
|
-
|
|
8108
|
+
/* Alerta: tiembla, ojos redondos de aviso y ondas naranjas. */
|
|
8109
|
+
.aurora-linda-mascot--alert .aurora-lm-body {
|
|
8110
|
+
animation: aurora-lm-float var(--_lm-breath) ease-in-out infinite, aurora-lm-shake 2.6s ease-in-out infinite;
|
|
8111
|
+
}
|
|
8112
|
+
.aurora-linda-mascot--alert .aurora-lm-eyes {
|
|
8113
|
+
transform: translate(-50%, -50%) scale(1.08);
|
|
8114
|
+
}
|
|
8115
|
+
.aurora-linda-mascot--alert .aurora-lm-eye {
|
|
8116
|
+
height: auto;
|
|
8117
|
+
aspect-ratio: 1;
|
|
8118
|
+
border-radius: 50%;
|
|
8119
|
+
box-shadow: 0 0 ${s(0.025)} var(--_lm-light), 0 0 ${s(0.08)} var(--_lm-alert);
|
|
8120
|
+
animation: aurora-lm-alert-pop 1.6s ease-out infinite;
|
|
8121
|
+
}
|
|
8122
|
+
.aurora-linda-mascot--alert .aurora-lm-pulse {
|
|
8123
|
+
border-color: var(--_lm-alert);
|
|
8124
|
+
animation: aurora-lm-ping 1.6s ease-out infinite;
|
|
8125
|
+
}
|
|
8126
|
+
.aurora-linda-mascot--alert .aurora-lm-pulse--2 {
|
|
8127
|
+
animation-delay: 0.8s;
|
|
7260
8128
|
}
|
|
7261
|
-
.aurora-linda-mascot--
|
|
7262
|
-
|
|
8129
|
+
.aurora-linda-mascot--alert .aurora-lm-bubble {
|
|
8130
|
+
box-shadow: inset ${s(-0.03)} ${s(-0.04)} ${s(0.07)} ${mix("core", 14)}, inset 0 0 ${s(0.06)} ${mix("alert", 35)}, 0 0 ${s(0.06)} ${mix("alert", 35)}, 0 0 ${s(0.14)} ${mix("alert-deep", 20)};
|
|
7263
8131
|
}
|
|
7264
8132
|
|
|
7265
|
-
|
|
7266
|
-
|
|
8133
|
+
/* Cargando: rebota una vez y en el segundo salto se vuelve 9 puntos que giran. */
|
|
8134
|
+
.aurora-linda-mascot--loading .aurora-lm-body {
|
|
8135
|
+
transform-origin: 50% 90%;
|
|
8136
|
+
animation: aurora-lm-load-body 6s cubic-bezier(0.45, 0, 0.35, 1) infinite;
|
|
7267
8137
|
}
|
|
7268
|
-
.aurora-linda-mascot--
|
|
7269
|
-
|
|
7270
|
-
|
|
8138
|
+
.aurora-linda-mascot--loading .aurora-lm-shadow {
|
|
8139
|
+
animation: aurora-lm-load-shadow 6s ease-in-out infinite;
|
|
8140
|
+
}
|
|
8141
|
+
.aurora-linda-mascot--loading .aurora-lm-pulse {
|
|
8142
|
+
opacity: 0;
|
|
8143
|
+
}
|
|
8144
|
+
.aurora-linda-mascot--loading .aurora-lm-load {
|
|
8145
|
+
display: grid;
|
|
8146
|
+
animation: aurora-lm-load-grid 6s ease-in-out infinite;
|
|
8147
|
+
}
|
|
8148
|
+
.aurora-linda-mascot--loading .aurora-lm-dot {
|
|
8149
|
+
animation-name: aurora-lm-load-dot;
|
|
8150
|
+
animation-duration: 1.2s;
|
|
8151
|
+
animation-timing-function: ease-in-out;
|
|
8152
|
+
animation-iteration-count: infinite;
|
|
8153
|
+
}
|
|
8154
|
+
.aurora-linda-mascot--loading .aurora-lm-dot--5 {
|
|
8155
|
+
animation: none;
|
|
8156
|
+
opacity: 0.3;
|
|
7271
8157
|
}
|
|
7272
8158
|
|
|
7273
|
-
|
|
7274
|
-
|
|
7275
|
-
|
|
8159
|
+
/* ── Talla avatar: fuera lo que a 20 px es ruido ─────────────────────────── */
|
|
8160
|
+
|
|
8161
|
+
.aurora-linda-mascot--tier-xs::after,
|
|
8162
|
+
.aurora-linda-mascot--tier-xs .aurora-lm-shadow {
|
|
8163
|
+
display: none;
|
|
7276
8164
|
}
|
|
7277
8165
|
|
|
7278
8166
|
/* ── Keyframes ───────────────────────────────────────────────────────────── */
|
|
7279
8167
|
|
|
7280
|
-
@keyframes aurora-lm-
|
|
7281
|
-
to {
|
|
7282
|
-
transform: rotate(360deg);
|
|
7283
|
-
}
|
|
8168
|
+
@keyframes aurora-lm-hue {
|
|
8169
|
+
to { --aurora-lm-a: 360deg; }
|
|
7284
8170
|
}
|
|
7285
|
-
@keyframes aurora-lm-
|
|
7286
|
-
|
|
7287
|
-
transform: scale(1);
|
|
7288
|
-
}
|
|
7289
|
-
to {
|
|
7290
|
-
transform: scale(1.03);
|
|
7291
|
-
}
|
|
8171
|
+
@keyframes aurora-lm-spin {
|
|
8172
|
+
to { transform: rotate(360deg); }
|
|
7292
8173
|
}
|
|
7293
|
-
@keyframes aurora-lm-
|
|
7294
|
-
0%,
|
|
7295
|
-
|
|
7296
|
-
}
|
|
7297
|
-
43.5%, 98.8% {
|
|
7298
|
-
transform: scaleY(0.12);
|
|
7299
|
-
}
|
|
8174
|
+
@keyframes aurora-lm-float {
|
|
8175
|
+
0%, 100% { transform: translateY(0); }
|
|
8176
|
+
50% { transform: translateY(${s(-0.025)}); }
|
|
7300
8177
|
}
|
|
7301
|
-
@keyframes aurora-lm-
|
|
7302
|
-
0%, 100% {
|
|
7303
|
-
|
|
7304
|
-
opacity: calc(var(--lm-halo) * var(--lm-halo-boost, 1));
|
|
7305
|
-
}
|
|
7306
|
-
50% {
|
|
7307
|
-
transform: scale(1.12);
|
|
7308
|
-
opacity: 1;
|
|
7309
|
-
}
|
|
8178
|
+
@keyframes aurora-lm-squish {
|
|
8179
|
+
0%, 100% { transform: scale(1, 1); }
|
|
8180
|
+
50% { transform: scale(1.035, 0.965) translateY(1.5%); }
|
|
7310
8181
|
}
|
|
7311
|
-
@keyframes aurora-lm-
|
|
7312
|
-
0%, 100% {
|
|
7313
|
-
|
|
7314
|
-
}
|
|
7315
|
-
50% {
|
|
7316
|
-
opacity: 1;
|
|
7317
|
-
}
|
|
8182
|
+
@keyframes aurora-lm-shadow {
|
|
8183
|
+
0%, 100% { transform: scale(1); opacity: 1; }
|
|
8184
|
+
50% { transform: scale(0.86); opacity: 0.7; }
|
|
7318
8185
|
}
|
|
7319
|
-
@keyframes aurora-lm-
|
|
7320
|
-
0% {
|
|
7321
|
-
|
|
7322
|
-
|
|
7323
|
-
|
|
7324
|
-
|
|
7325
|
-
|
|
7326
|
-
|
|
7327
|
-
|
|
7328
|
-
100% {
|
|
7329
|
-
|
|
7330
|
-
|
|
7331
|
-
|
|
8186
|
+
@keyframes aurora-lm-blink {
|
|
8187
|
+
0%, 93%, 100% { transform: scaleY(1); }
|
|
8188
|
+
96% { transform: scaleY(0.08); }
|
|
8189
|
+
}
|
|
8190
|
+
@keyframes aurora-lm-ping {
|
|
8191
|
+
0% { transform: scale(0.92); opacity: 0.85; }
|
|
8192
|
+
100% { transform: scale(1.55); opacity: 0; }
|
|
8193
|
+
}
|
|
8194
|
+
@keyframes aurora-lm-flicker {
|
|
8195
|
+
0%, 100% { opacity: 1; }
|
|
8196
|
+
50% { opacity: 0.72; }
|
|
8197
|
+
}
|
|
8198
|
+
@keyframes aurora-lm-tilt {
|
|
8199
|
+
0%, 100% { rotate: -9deg; }
|
|
8200
|
+
50% { rotate: 9deg; }
|
|
8201
|
+
}
|
|
8202
|
+
@keyframes aurora-lm-think {
|
|
8203
|
+
0%, 100% { translate: -16% -10%; }
|
|
8204
|
+
40% { translate: 16% -20%; }
|
|
8205
|
+
70% { translate: 0 -6%; }
|
|
8206
|
+
}
|
|
8207
|
+
@keyframes aurora-lm-scan {
|
|
8208
|
+
0%, 100% { translate: -18% 0; }
|
|
8209
|
+
50% { translate: 18% 0; }
|
|
8210
|
+
}
|
|
8211
|
+
@keyframes aurora-lm-buzz {
|
|
8212
|
+
0%, 100% { translate: 0 0; }
|
|
8213
|
+
25% { translate: 0 ${s(-0.025)}; }
|
|
8214
|
+
75% { translate: 0 ${s(0.015)}; }
|
|
8215
|
+
}
|
|
8216
|
+
@keyframes aurora-lm-shake {
|
|
8217
|
+
0%, 65%, 100% { rotate: 0deg; }
|
|
8218
|
+
70% { rotate: -12deg; }
|
|
8219
|
+
76% { rotate: 12deg; }
|
|
8220
|
+
82% { rotate: -8deg; }
|
|
8221
|
+
88% { rotate: 5deg; }
|
|
8222
|
+
94% { rotate: -2deg; }
|
|
8223
|
+
}
|
|
8224
|
+
@keyframes aurora-lm-ready {
|
|
8225
|
+
0%, 100% { translate: 0 0; }
|
|
8226
|
+
50% { translate: 0 ${s(-0.018)}; }
|
|
8227
|
+
}
|
|
8228
|
+
@keyframes aurora-lm-squint {
|
|
8229
|
+
0%, 22%, 100% { scale: 1 1; }
|
|
8230
|
+
34%, 70% { scale: 1.06 0.38; }
|
|
8231
|
+
82% { scale: 1 1.06; }
|
|
8232
|
+
}
|
|
8233
|
+
@keyframes aurora-lm-alert-pop {
|
|
8234
|
+
0%, 100% { scale: 1.22 1.22; }
|
|
8235
|
+
12% { scale: 1.38 1.38; }
|
|
8236
|
+
24% { scale: 1.22 1.22; }
|
|
8237
|
+
}
|
|
8238
|
+
@keyframes aurora-lm-listen-wave {
|
|
8239
|
+
0% { scale: 0.97; opacity: 0; border-width: ${s(0.014)}; }
|
|
8240
|
+
18% { opacity: 0.75; }
|
|
8241
|
+
100% { scale: 1.42; opacity: 0; border-width: ${s(0.002)}; }
|
|
8242
|
+
}
|
|
8243
|
+
@keyframes aurora-lm-nod {
|
|
8244
|
+
0%, 55%, 100% { translate: 0 0; rotate: 0deg; }
|
|
8245
|
+
8% { translate: 0 ${s(0.06)}; rotate: 3deg; }
|
|
8246
|
+
16% { translate: 0 ${s(-0.018)}; rotate: 0deg; }
|
|
8247
|
+
24% { translate: 0 ${s(0.06)}; rotate: 3deg; }
|
|
8248
|
+
32% { translate: 0 0; rotate: 0deg; }
|
|
8249
|
+
}
|
|
8250
|
+
@keyframes aurora-lm-nod-eyes {
|
|
8251
|
+
0%, 55%, 100% { translate: 0 0; }
|
|
8252
|
+
8% { translate: 0 26%; }
|
|
8253
|
+
16% { translate: 0 -8%; }
|
|
8254
|
+
24% { translate: 0 26%; }
|
|
8255
|
+
32% { translate: 0 0; }
|
|
8256
|
+
}
|
|
8257
|
+
@keyframes aurora-lm-jabon {
|
|
8258
|
+
0%, 100% { border-radius: 62% 38% 56% 44% / 44% 60% 40% 56%; }
|
|
8259
|
+
17% { border-radius: 52% 48% 64% 36% / 38% 54% 46% 62%; }
|
|
8260
|
+
33% { border-radius: 40% 60% 50% 50% / 56% 44% 60% 40%; }
|
|
8261
|
+
50% { border-radius: 46% 54% 38% 62% / 62% 50% 50% 38%; }
|
|
8262
|
+
67% { border-radius: 58% 42% 44% 56% / 50% 62% 38% 50%; }
|
|
8263
|
+
83% { border-radius: 66% 34% 52% 48% / 42% 48% 52% 58%; }
|
|
7332
8264
|
}
|
|
7333
|
-
@keyframes aurora-lm-
|
|
7334
|
-
0%, 100% {
|
|
7335
|
-
|
|
7336
|
-
}
|
|
7337
|
-
|
|
7338
|
-
|
|
7339
|
-
|
|
8265
|
+
@keyframes aurora-lm-breathe {
|
|
8266
|
+
0%, 100% { scale: 1.05 0.96; }
|
|
8267
|
+
25% { scale: 0.98 1.03; }
|
|
8268
|
+
50% { scale: 0.95 1.06; }
|
|
8269
|
+
75% { scale: 1.03 0.98; }
|
|
8270
|
+
}
|
|
8271
|
+
@keyframes aurora-lm-drift {
|
|
8272
|
+
from { rotate: 0deg; }
|
|
8273
|
+
to { rotate: 360deg; }
|
|
8274
|
+
}
|
|
8275
|
+
@keyframes aurora-lm-load-body {
|
|
8276
|
+
0%, 100% { translate: 0 0; scale: 1 1; opacity: 1; filter: blur(0); }
|
|
8277
|
+
5% { translate: 0 ${s(0.04)}; scale: 1.1 0.86; opacity: 1; }
|
|
8278
|
+
13% { translate: 0 ${s(-0.22)}; scale: 0.94 1.06; opacity: 1; }
|
|
8279
|
+
20% { translate: 0 ${s(0.03)}; scale: 1.08 0.9; opacity: 1; }
|
|
8280
|
+
24% { translate: 0 0; scale: 1 1; opacity: 1; }
|
|
8281
|
+
28% { translate: 0 ${s(0.04)}; scale: 1.1 0.86; opacity: 1; }
|
|
8282
|
+
37% { translate: 0 ${s(-0.3)}; scale: 0.92 1.08; opacity: 1; }
|
|
8283
|
+
44% { translate: 0 ${s(-0.05)}; scale: 0.25 0.25; opacity: 0; }
|
|
8284
|
+
80% { translate: 0 ${s(-0.28)}; scale: 0.45 0.45; opacity: 0; filter: blur(${s(0.02)}); }
|
|
8285
|
+
86% { translate: 0 ${s(-0.14)}; scale: 0.92 1.06; opacity: 1; filter: blur(0); }
|
|
8286
|
+
90% { translate: 0 ${s(0.04)}; scale: 1.14 0.84; opacity: 1; }
|
|
8287
|
+
94% { translate: 0 ${s(-0.09)}; scale: 0.95 1.06; opacity: 1; }
|
|
8288
|
+
97% { translate: 0 ${s(0.015)}; scale: 1.05 0.95; opacity: 1; }
|
|
8289
|
+
}
|
|
8290
|
+
@keyframes aurora-lm-load-shadow {
|
|
8291
|
+
0%, 24%, 100% { opacity: 1; scale: 1; }
|
|
8292
|
+
13% { opacity: 0.5; scale: 0.7; }
|
|
8293
|
+
37% { opacity: 0.4; scale: 0.6; }
|
|
8294
|
+
44%, 84% { opacity: 0.5; scale: 0.5; }
|
|
8295
|
+
}
|
|
8296
|
+
@keyframes aurora-lm-load-grid {
|
|
8297
|
+
0%, 41% { opacity: 0; scale: 0.3; rotate: -30deg; }
|
|
8298
|
+
49% { opacity: 1; scale: 1.08; rotate: 0deg; }
|
|
8299
|
+
54%, 76% { opacity: 1; scale: 1; rotate: 0deg; filter: blur(0); }
|
|
8300
|
+
90%, 100% { opacity: 0; scale: 0.55; rotate: 12deg; filter: blur(${s(0.02)}); }
|
|
8301
|
+
}
|
|
8302
|
+
@keyframes aurora-lm-load-dot {
|
|
8303
|
+
0%, 100% { opacity: 0.35; scale: 0.8; }
|
|
8304
|
+
12%, 30% { opacity: 1; scale: 1.08; }
|
|
8305
|
+
48% { opacity: 0.35; scale: 0.8; }
|
|
7340
8306
|
}
|
|
7341
8307
|
|
|
7342
8308
|
/*
|
|
7343
|
-
* Movimiento reducido: nada
|
|
7344
|
-
*
|
|
7345
|
-
*
|
|
7346
|
-
* o se enciende; con la voz sube la opacidad del halo y de los anillos; las chispas
|
|
7347
|
-
* aparecen y se desvanecen sin moverse.
|
|
7348
|
-
*
|
|
7349
|
-
* Las mismas reglas se aplican con la preferencia del sistema y con \`motion="reduce"\`
|
|
7350
|
-
* (\`data-motion\`), que el consumidor usa para listas largas o para forzarlo. \`!important\`
|
|
7351
|
-
* porque las reglas por estado de arriba tienen más especificidad y \`@media\` no la sube.
|
|
8309
|
+
* Movimiento reducido: nada se mueve. Cada estado se sigue leyendo por sus colores, sus
|
|
8310
|
+
* ojos y sus accesorios (gafas, auriculares, órbitas); cargando se queda en la cuadrícula.
|
|
8311
|
+
* Las mismas reglas con la preferencia del sistema y con \`motion="reduce"\`.
|
|
7352
8312
|
*/
|
|
7353
|
-
|
|
8313
|
+
@media (prefers-reduced-motion: reduce) {${reducedMotion(ROOT)}}
|
|
8314
|
+
${reducedMotion(`${ROOT}[data-motion="reduce"]`)}
|
|
7354
8315
|
`;
|
|
7355
8316
|
|
|
7356
|
-
const CX = 60;
|
|
7357
8317
|
const STYLE_ID = styleIdFor(LINDA_MASCOT_STYLE_ID, LINDA_MASCOT_CSS);
|
|
7358
|
-
/**
|
|
7359
|
-
const
|
|
7360
|
-
|
|
7361
|
-
|
|
7362
|
-
{ duration: "36s", direction: "normal" },
|
|
7363
|
-
];
|
|
7364
|
-
/** Chispas de `ready`: posición en el viewBox, tamaño y retardo. */
|
|
7365
|
-
const SPARKLES = [
|
|
7366
|
-
{ x: 90, y: 17, s: 9, delay: "0ms" },
|
|
7367
|
-
{ x: 104, y: 35, s: 5.5, delay: "90ms" },
|
|
7368
|
-
{ x: 73, y: 7, s: 4.5, delay: "170ms" },
|
|
7369
|
-
];
|
|
7370
|
-
const sparklePath = (s) => {
|
|
7371
|
-
const k = s * 0.18;
|
|
7372
|
-
return `M0 ${-s}C${k} ${-k} ${k} ${-k} ${s} 0C${k} ${k} ${k} ${k} 0 ${s}C${-k} ${k} ${-k} ${k} ${-s} 0C${-k} ${-k} ${-k} ${-k} 0 ${-s}Z`;
|
|
7373
|
-
};
|
|
8318
|
+
/** Los 9 puntos de cargando, en el orden de la cuadrícula (fila a fila). */
|
|
8319
|
+
const LOAD_DOTS = [1, 2, 3, 4, 5, 6, 7, 8, 9];
|
|
8320
|
+
/** Las 13 capas de reflejos de la pompa; cada una se dibuja por su posición. */
|
|
8321
|
+
const SOAP_LAYERS = Array.from({ length: 13 }, (_, index) => index + 1);
|
|
7374
8322
|
/**
|
|
7375
|
-
*
|
|
7376
|
-
*
|
|
7377
|
-
* que el cometa se dimensiona como fracción de este perímetro para medir lo mismo a
|
|
7378
|
-
* cualquier talla.
|
|
8323
|
+
* Las gafas de trabajar: dos ojos de gato y un puente, en la caja de 200 × 90 del lienzo.
|
|
8324
|
+
* Van en línea, dibujadas aquí, para no depender de ningún recurso externo.
|
|
7379
8325
|
*/
|
|
7380
|
-
const
|
|
7381
|
-
const a = (ring.r * px) / 120;
|
|
7382
|
-
const b = a * ring.squash;
|
|
7383
|
-
const h = ((a - b) / (a + b)) ** 2;
|
|
7384
|
-
return Math.PI * (a + b) * (1 + (3 * h) / (10 + Math.sqrt(4 - 3 * h)));
|
|
7385
|
-
};
|
|
8326
|
+
const Glasses = () => (jsxRuntime.jsx("svg", { className: "aurora-lm-glasses", "data-part": "glasses", viewBox: "0 0 200 90", "aria-hidden": "true", focusable: "false", children: jsxRuntime.jsxs("g", { children: [jsxRuntime.jsx("ellipse", { cx: "51", cy: "45", rx: "38", ry: "34" }), jsxRuntime.jsx("ellipse", { cx: "149", cy: "45", rx: "38", ry: "34" }), jsxRuntime.jsx("path", { d: "M89 40 Q 100 32 111 40" })] }) }));
|
|
7386
8327
|
/**
|
|
7387
|
-
*
|
|
7388
|
-
* iridiscente
|
|
7389
|
-
* redonda y brillante al final. Todo es `stroke-dasharray` sobre el mismo círculo que el
|
|
7390
|
-
* anillo, así que gira con `transform` y se recorta delante/detrás igual que él. El giro
|
|
7391
|
-
* es horario: la cabeza va al final del trazo, por delante de su cola.
|
|
7392
|
-
*/
|
|
7393
|
-
const Comet = ({ className, r, perimeter, tail, strokePx, headPx, steps, ringPaint, headPaint, }) => {
|
|
7394
|
-
const tailPx = perimeter * tail;
|
|
7395
|
-
const seg = tailPx / steps;
|
|
7396
|
-
return (jsxRuntime.jsxs("g", { className: className, "data-part": "comet", children: [Array.from({ length: steps }, (_, i) => {
|
|
7397
|
-
const t = (i + 1) / steps;
|
|
7398
|
-
return (jsxRuntime.jsx("circle", { r: r, fill: "none", stroke: ringPaint, strokeWidth: strokePx * (0.8 + 1.6 * t), strokeOpacity: t ** 1.5, strokeDasharray: `${(seg + 0.4).toFixed(2)} ${(perimeter - seg - 0.4).toFixed(2)}`, strokeDashoffset: (-seg * i).toFixed(2), vectorEffect: "non-scaling-stroke" }, i));
|
|
7399
|
-
}), jsxRuntime.jsx("circle", { r: r, fill: "none", stroke: headPaint, strokeWidth: headPx * 1.5, strokeOpacity: 0.3, strokeLinecap: "round", strokeDasharray: `0.01 ${(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 ${(perimeter - 0.01).toFixed(2)}`, strokeDashoffset: (-tailPx).toFixed(2), vectorEffect: "non-scaling-stroke" })] }));
|
|
7400
|
-
};
|
|
7401
|
-
/** Arco «∩» de un ojo centrado en (x, y): ancho w, alto h. */
|
|
7402
|
-
const eyePath = (x, y, w, h) => {
|
|
7403
|
-
const half = w / 2;
|
|
7404
|
-
const base = y + h / 2;
|
|
7405
|
-
const control = y - h * 0.8333;
|
|
7406
|
-
return `M${x - half} ${base}C${x - half} ${control} ${x + half} ${control} ${x + half} ${base}`;
|
|
7407
|
-
};
|
|
7408
|
-
/**
|
|
7409
|
-
* `useId` devuelve `:r0:` (React 18), `«r0»` o `_r_0_` (19): fuera lo que no vale en un
|
|
7410
|
-
* id referenciado desde `url(#…)`.
|
|
7411
|
-
*/
|
|
7412
|
-
const safeId = (raw) => `lm${raw.replace(/[^a-zA-Z0-9_-]/g, "")}`;
|
|
7413
|
-
/**
|
|
7414
|
-
* LindaMascot — la cara de Linda: un orbe de tinta con ojos luminosos y anillos
|
|
7415
|
-
* iridiscentes, en SVG + CSS (sin imágenes, fuentes ni WebGL).
|
|
8328
|
+
* LindaMascot — el personaje del agente: un núcleo oscuro con dos ojos de luz, un aro
|
|
8329
|
+
* iridiscente y una pompa de jabón alrededor, en HTML + CSS (sin imágenes ni fuentes).
|
|
7416
8330
|
*
|
|
7417
|
-
*
|
|
7418
|
-
*
|
|
7419
|
-
*
|
|
8331
|
+
* Sus colores son dato: los lee de las variables `--lm-*` que escribe
|
|
8332
|
+
* `applyCharacterPalette` (o de la prop `palette`) y, sin ellas, se pinta como Linda.
|
|
8333
|
+
* Se anima según lo que está haciendo (`state`) y, en la llamada de voz, según el volumen
|
|
8334
|
+
* (`level`). Ver README.
|
|
7420
8335
|
*/
|
|
7421
|
-
const LindaMascot = $8WNJc$react.forwardRef(function LindaMascot({ state
|
|
8336
|
+
const LindaMascot = $8WNJc$react.forwardRef(function LindaMascot({ state, size = "md", level, label, appearance = "auto", motion = "auto", palette, className, style, ...spanProps }, ref) {
|
|
7422
8337
|
useInjectedStyle(STYLE_ID, LINDA_MASCOT_CSS);
|
|
7423
|
-
const
|
|
8338
|
+
const visualState = resolveMascotState(state);
|
|
7424
8339
|
const px = resolveMascotPx(size);
|
|
7425
8340
|
const tier = resolveMascotTier(px);
|
|
7426
|
-
const
|
|
7427
|
-
const coreRy = g.coreRx * 0.92;
|
|
7428
|
-
const eyeY = g.coreCy - coreRy + coreRy * 2 * 0.45;
|
|
7429
|
-
const eyes = [CX - g.eyeGap / 2, CX + g.eyeGap / 2];
|
|
7430
|
-
// Recorte delante/detrás: en lg los velos desenfocados salen más allá del anillo.
|
|
7431
|
-
const clipHalf = g.ringGlow === "blur" ? 120 : 80;
|
|
7432
|
-
const id = {
|
|
7433
|
-
core: `${uid}-core`,
|
|
7434
|
-
coreClip: `${uid}-core-clip`,
|
|
7435
|
-
rim: `${uid}-rim`,
|
|
7436
|
-
ring: `${uid}-ring`,
|
|
7437
|
-
halo: `${uid}-halo`,
|
|
7438
|
-
shadow: `${uid}-shadow`,
|
|
7439
|
-
specular: `${uid}-specular`,
|
|
7440
|
-
back: `${uid}-back`,
|
|
7441
|
-
front: `${uid}-front`,
|
|
7442
|
-
soft: `${uid}-soft`,
|
|
7443
|
-
eyeGlow: `${uid}-eye-glow`,
|
|
7444
|
-
aura: `${uid}-aura`,
|
|
7445
|
-
veil: `${uid}-veil`,
|
|
7446
|
-
tail: `${uid}-tail`,
|
|
7447
|
-
};
|
|
8341
|
+
const paletteVars = $8WNJc$react.useMemo(() => (palette ? characterPaletteToCssVars(palette) : undefined), [palette]);
|
|
7448
8342
|
const a11y = label
|
|
7449
8343
|
? { role: "img", "aria-label": label }
|
|
7450
8344
|
: { "aria-hidden": true };
|
|
7451
|
-
|
|
7452
|
-
const motion = RING_MOTION[index];
|
|
7453
|
-
const spinStyle = {
|
|
7454
|
-
"--lm-spin-duration": motion.duration,
|
|
7455
|
-
"--lm-spin-direction": motion.direction,
|
|
7456
|
-
};
|
|
7457
|
-
const isMain = index === 0;
|
|
7458
|
-
const perimeter = ringPerimeterPx(ring, px);
|
|
7459
|
-
return (jsxRuntime.jsx("g", { "data-ring": index + 1, "data-ring-half": half, transform: `translate(${CX} ${g.coreCy}) rotate(${ring.tilt})`, opacity: half === "back" ? ring.opacity * 0.62 : ring.opacity, children: jsxRuntime.jsx("g", { clipPath: `url(#${half === "back" ? id.back : id.front})`, children: jsxRuntime.jsxs("g", { transform: `scale(1 ${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(#${id.ring})`, strokeWidth: ring.strokePx * 16, strokeOpacity: 0.3, vectorEffect: "non-scaling-stroke", filter: `url(#${id.veil})` })), g.ringGlow !== "none" && (jsxRuntime.jsx("circle", { r: ring.r, fill: "none", stroke: `url(#${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(#${id.soft})` : undefined })), g.ringGlow !== "none" && (jsxRuntime.jsx("circle", { r: ring.r + 2.2, fill: "none", stroke: `url(#${id.ring})`, strokeWidth: ring.strokePx * 0.55, strokeOpacity: 0.55, vectorEffect: "non-scaling-stroke" })), jsxRuntime.jsx("circle", { r: ring.r, fill: "none", stroke: `url(#${id.ring})`, strokeWidth: ring.strokePx, vectorEffect: "non-scaling-stroke" })] }) }), isMain && (jsxRuntime.jsxs("g", { className: "aurora-lm-spin aurora-lm-orbit", style: {
|
|
7460
|
-
"--lm-spin-duration": "1.6s",
|
|
7461
|
-
}, 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(#${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(#${id.tail})`, headPaint: LINDA_MASCOT_PALETTE.eyeGlow })] }))] }) }) }, `${half}-${index}`));
|
|
7462
|
-
};
|
|
7463
|
-
const ringHalves = (half) => g.rings.map((ring, index) => renderRing(ring, index, half));
|
|
7464
|
-
return (
|
|
7465
|
-
// 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`.
|
|
7466
|
-
jsxRuntime.jsxs("svg", { ref: ref, xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 120 120", width: px, height: px, focusable: "false", className: [
|
|
8345
|
+
return (jsxRuntime.jsxs("span", { ref: ref, className: [
|
|
7467
8346
|
"aurora-linda-mascot",
|
|
7468
|
-
`aurora-linda-mascot--${
|
|
8347
|
+
`aurora-linda-mascot--${visualState}`,
|
|
7469
8348
|
`aurora-linda-mascot--tier-${tier}`,
|
|
7470
8349
|
className,
|
|
7471
8350
|
]
|
|
7472
8351
|
.filter(Boolean)
|
|
7473
|
-
.join(" "), "data-state":
|
|
8352
|
+
.join(" "), "data-state": visualState, "data-tier": tier, "data-appearance": appearance, "data-motion": motion, style: {
|
|
8353
|
+
...paletteVars,
|
|
7474
8354
|
...style,
|
|
8355
|
+
"--_lm-size": `${px}px`,
|
|
7475
8356
|
[LINDA_MASCOT_LEVEL_VAR]: clampLevel(level),
|
|
7476
|
-
}, ...a11y, ...
|
|
7477
|
-
"--lm-sparkle-delay": s.delay,
|
|
7478
|
-
} }) }, `${s.x}-${s.y}`))) }))] }) })] }));
|
|
8357
|
+
}, ...a11y, ...spanProps, children: [jsxRuntime.jsx("span", { className: "aurora-lm-pulse", "data-part": "pulse" }), jsxRuntime.jsx("span", { className: "aurora-lm-pulse aurora-lm-pulse--2", "data-part": "pulse" }), tier !== "xs" && (jsxRuntime.jsx("span", { className: "aurora-lm-shadow", "data-part": "shadow" })), jsxRuntime.jsx("span", { className: "aurora-lm-load", "data-part": "load", children: LOAD_DOTS.map((dot) => (jsxRuntime.jsx("span", { className: `aurora-lm-dot aurora-lm-dot--${dot}`, "data-part": "load-dot" }, dot))) }), jsxRuntime.jsx("span", { className: "aurora-lm-level", "data-part": "level", children: jsxRuntime.jsxs("span", { className: "aurora-lm-body", "data-part": "body", children: [jsxRuntime.jsx("span", { className: "aurora-lm-rimglow", children: jsxRuntime.jsx("span", { className: "aurora-lm-rim-glow", "data-part": "rim-glow" }) }), jsxRuntime.jsx("span", { className: "aurora-lm-core", "data-part": "core" }), jsxRuntime.jsx("span", { className: "aurora-lm-rim", "data-part": "rim" }), jsxRuntime.jsx("span", { className: "aurora-lm-rimline", "data-part": "rimline" }), jsxRuntime.jsxs("span", { className: "aurora-lm-orbits", "data-part": "orbits", children: [jsxRuntime.jsx("span", { className: "aurora-lm-orbit", "data-part": "orbit" }), jsxRuntime.jsx("span", { className: "aurora-lm-orbit aurora-lm-orbit--2", "data-part": "orbit" }), jsxRuntime.jsx("span", { className: "aurora-lm-orbit aurora-lm-orbit--3", "data-part": "orbit" })] }), jsxRuntime.jsxs("span", { className: "aurora-lm-eyes", "data-part": "eyes", children: [jsxRuntime.jsx("span", { className: "aurora-lm-eye", "data-part": "eye" }), jsxRuntime.jsx("span", { className: "aurora-lm-eye", "data-part": "eye" }), visualState === "working" && jsxRuntime.jsx(Glasses, {})] }), jsxRuntime.jsx("span", { className: "aurora-lm-bubble", "data-part": "bubble" }), jsxRuntime.jsx("span", { className: "aurora-lm-soap", "data-part": "soap", children: SOAP_LAYERS.map((layer) => (jsxRuntime.jsx("span", {}, layer))) }), visualState === "listening" && tier !== "xs" && (jsxRuntime.jsxs("span", { className: "aurora-lm-headphones", "data-part": "headphones", children: [jsxRuntime.jsx("span", { className: "aurora-lm-headphones-arc" }), jsxRuntime.jsx("span", { className: "aurora-lm-headphones-cup aurora-lm-headphones-cup--left" }), jsxRuntime.jsx("span", { className: "aurora-lm-headphones-cup aurora-lm-headphones-cup--right" })] }))] }) })] }));
|
|
7479
8358
|
});
|
|
7480
8359
|
|
|
8360
|
+
/**
|
|
8361
|
+
* El tema del personaje que ve una agencia que no ha elegido ninguno: el que corresponde a
|
|
8362
|
+
* su tema de color de la plataforma. `blue` es el de Bewe y se pinta como Linda; los
|
|
8363
|
+
* otros seis tienen un tema del personaje con el mismo color. Luna no aparece: es un tema
|
|
8364
|
+
* propio de Gurú, no uno de plataforma.
|
|
8365
|
+
*/
|
|
8366
|
+
const PLATFORM_THEME_TO_CHARACTER_THEME = {
|
|
8367
|
+
blue: "linda",
|
|
8368
|
+
purple: "purple",
|
|
8369
|
+
coral: "coral",
|
|
8370
|
+
green: "green",
|
|
8371
|
+
oceanMint: "ocean",
|
|
8372
|
+
skyBlue: "sky",
|
|
8373
|
+
yellow: "yellow",
|
|
8374
|
+
};
|
|
8375
|
+
/**
|
|
8376
|
+
* El tema del personaje para un tema de plataforma.
|
|
8377
|
+
*
|
|
8378
|
+
* Acepta el color solo (`purple`) y el nombre con modo que usa el tema de aurora
|
|
8379
|
+
* (`purple-dark`). Todo lo demás —vacío, un hex a medida, `light`/`dark` sueltos (el azul
|
|
8380
|
+
* de siempre) o un nombre desconocido— cae a Linda.
|
|
8381
|
+
*/
|
|
8382
|
+
const characterThemeForPlatformTheme = (value) => {
|
|
8383
|
+
if (typeof value !== "string") {
|
|
8384
|
+
return DEFAULT_CHARACTER_THEME_ID;
|
|
8385
|
+
}
|
|
8386
|
+
const color = value.trim().replace(/-(light|dark)$/, "");
|
|
8387
|
+
return Object.prototype.hasOwnProperty.call(PLATFORM_THEME_TO_CHARACTER_THEME, color)
|
|
8388
|
+
? PLATFORM_THEME_TO_CHARACTER_THEME[color]
|
|
8389
|
+
: DEFAULT_CHARACTER_THEME_ID;
|
|
8390
|
+
};
|
|
8391
|
+
|
|
7481
8392
|
const defaultTranslations$8 = {
|
|
7482
8393
|
previewAlt: "Vista previa de imagen",
|
|
7483
8394
|
removeButtonAriaLabel: "Eliminar imagen",
|
|
@@ -13848,7 +14759,7 @@ size, width = "100%", height = "auto", multiple = false, maxFiles = 1, maxFileSi
|
|
|
13848
14759
|
? "opacity-0"
|
|
13849
14760
|
: "opacity-100 transition-opacity", children: jsxRuntime.jsxs("div", { className: `flex flex-col items-center ${size === "micro" ? "gap-0" : size === "small" ? "gap-0.5" : "gap-1"}`, children: [jsxRuntime.jsx(IconComponent, { icon: icon, size: size === "micro" ? "sm" : size === "small" ? "md" : "lg", className: `${size === "micro" ? "text-sm"
|
|
13850
14761
|
: size === "small" ? "text-base sm:text-lg"
|
|
13851
|
-
: "text-xl sm:text-2xl"} ${disabled ? "text-default-400" : iconColor || "text-
|
|
14762
|
+
: "text-xl sm:text-2xl"} ${disabled ? "text-default-400" : iconColor || "text-accent-soft-foreground"}` }), shouldShowText && (jsxRuntime.jsxs("div", { className: `text-center ${size === "micro" ? "px-0"
|
|
13852
14763
|
: size === "small" ? "px-0.5"
|
|
13853
14764
|
: "px-1"} ${size === "micro" || size === "small"
|
|
13854
14765
|
? "upload-file-dropzone-text"
|
|
@@ -14523,7 +15434,7 @@ const NavigationLoadingOverlay = ({ isVisible, }) => {
|
|
|
14523
15434
|
*/
|
|
14524
15435
|
const DrawerFiltersFooter = ({ onClearFilters, onCancel, onApplyFilters, translations = {}, }) => {
|
|
14525
15436
|
const { clearFilters = "Limpiar filtro", cancel = "Cancelar", applyFilters = "Aplicar filtro", } = translations;
|
|
14526
|
-
return (jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-6 py-10 bg-content1", children: [jsxRuntime.jsx(Button, { variant: "light", color: "primary", onPress: onClearFilters, className: "text-
|
|
15437
|
+
return (jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-6 py-10 bg-content1", children: [jsxRuntime.jsx(Button, { variant: "light", color: "primary", onPress: onClearFilters, className: "text-accent-soft-foreground", children: clearFilters }), jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [jsxRuntime.jsx(Button, { variant: "bordered", color: "primary", onPress: onCancel, children: cancel }), jsxRuntime.jsx(Button, { variant: "solid", color: "primary", onPress: onApplyFilters, children: applyFilters })] })] }));
|
|
14527
15438
|
};
|
|
14528
15439
|
|
|
14529
15440
|
/**
|
|
@@ -15068,7 +15979,7 @@ const MultiSelectFilter = ({ filter, value, onChange, translations, titleId }) =
|
|
|
15068
15979
|
classNames: {
|
|
15069
15980
|
inputWrapper: "bg-default-100 shadow-none border-0 min-h-9 h-9",
|
|
15070
15981
|
input: "text-sm",
|
|
15071
|
-
}, endContent: jsxRuntime.jsx(IconComponent, { icon: "solar:magnifer-outline", className: "pointer-events-none shrink-0 text-default-400", size: "sm", "aria-hidden": true }), "aria-label": searchPlaceholder }) })), jsxRuntime.jsx("div", { className: "max-h-60 overflow-y-auto px-1 py-1", children: filteredData.length === 0 ? (jsxRuntime.jsx("p", { className: "px-2 py-3 text-center text-xs text-default-400", children: noResultsText })) : (jsxRuntime.jsx(react.ListBox, { "aria-label": filter.title, selectionMode: "multiple", selectionBehavior: "toggle", selectedKeys: selectedKeys, onSelectionChange: handleListboxSelectionChange, disallowEmptySelection: false, className: "w-full gap-0.5 p-0", children: filteredData.map((item) => (jsxRuntime.jsx(react.ListBoxItem, { id: item.value, textValue: item.label, className: "rounded-[12px] px-2 py-2.5 text-sm font-normal text-default-600 data-[hovered=true]:bg-default-100 data-[selectable=true]:focus:bg-default-100 data-[selected=true]:bg-primary-50/80 data-[selected=true]:font-medium data-[selected=true]:text-
|
|
15982
|
+
}, endContent: jsxRuntime.jsx(IconComponent, { icon: "solar:magnifer-outline", className: "pointer-events-none shrink-0 text-default-400", size: "sm", "aria-hidden": true }), "aria-label": searchPlaceholder }) })), jsxRuntime.jsx("div", { className: "max-h-60 overflow-y-auto px-1 py-1", children: filteredData.length === 0 ? (jsxRuntime.jsx("p", { className: "px-2 py-3 text-center text-xs text-default-400", children: noResultsText })) : (jsxRuntime.jsx(react.ListBox, { "aria-label": filter.title, selectionMode: "multiple", selectionBehavior: "toggle", selectedKeys: selectedKeys, onSelectionChange: handleListboxSelectionChange, disallowEmptySelection: false, className: "w-full gap-0.5 p-0", children: filteredData.map((item) => (jsxRuntime.jsx(react.ListBoxItem, { id: item.value, textValue: item.label, className: "rounded-[12px] px-2 py-2.5 text-sm font-normal text-default-600 data-[hovered=true]:bg-default-100 data-[selectable=true]:focus:bg-default-100 data-[selected=true]:bg-primary-50/80 data-[selected=true]:font-medium data-[selected=true]:text-accent-soft-foreground", children: item.label }, item.value))) })) })] }) })] }));
|
|
15072
15983
|
};
|
|
15073
15984
|
// =========================================================================
|
|
15074
15985
|
// RANGE FILTER
|
|
@@ -17772,7 +18683,7 @@ const RADIUS_CLASS = {
|
|
|
17772
18683
|
*/
|
|
17773
18684
|
const FLAT_BASE = {
|
|
17774
18685
|
default: "bg-default-100 text-default-foreground dark:bg-default-50/50",
|
|
17775
|
-
primary: "bg-primary-50 text-
|
|
18686
|
+
primary: "bg-primary-50 text-accent-soft-foreground dark:bg-primary-50/50",
|
|
17776
18687
|
secondary: "bg-secondary-50 text-secondary-600 dark:bg-secondary-50/50",
|
|
17777
18688
|
success: "bg-success-50 text-success-700 dark:bg-success-50/50 dark:text-success",
|
|
17778
18689
|
warning: "bg-warning-50 text-warning-700 dark:bg-warning-50/50 dark:text-warning",
|
|
@@ -17790,7 +18701,7 @@ const FADED_BORDER = {
|
|
|
17790
18701
|
/** `bordered`: `colorVariants.bordered.<color>` (+ `border-small`, sin fondo). */
|
|
17791
18702
|
const BORDERED_BASE = {
|
|
17792
18703
|
default: "bg-transparent border-default text-foreground",
|
|
17793
|
-
primary: "bg-transparent border-primary text-
|
|
18704
|
+
primary: "bg-transparent border-primary text-accent-soft-foreground",
|
|
17794
18705
|
secondary: "bg-transparent border-secondary text-secondary",
|
|
17795
18706
|
success: "bg-transparent border-success text-success",
|
|
17796
18707
|
warning: "bg-transparent border-warning text-warning",
|
|
@@ -19126,6 +20037,7 @@ const THEME_COLOR_HEX_MAP = {
|
|
|
19126
20037
|
blue: "#006fee",
|
|
19127
20038
|
purple: "#7828c8",
|
|
19128
20039
|
yellow: "#ffd505",
|
|
20040
|
+
amberYellow: "#ffbf00",
|
|
19129
20041
|
green: "#16c964",
|
|
19130
20042
|
coral: "#ff4f4f",
|
|
19131
20043
|
skyBlue: "#60A5FA",
|
|
@@ -19149,6 +20061,15 @@ function colorDistance(a, b) {
|
|
|
19149
20061
|
return (a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2 + (a[2] - b[2]) ** 2;
|
|
19150
20062
|
}
|
|
19151
20063
|
const THEME_COLORS = Object.keys(THEME_COLOR_HEX_MAP);
|
|
20064
|
+
/**
|
|
20065
|
+
* Packs que solo se resuelven por coincidencia exacta de su hex, nunca como «el más
|
|
20066
|
+
* cercano». `amberYellow` es una variante oscura de `yellow` pensada para una marca
|
|
20067
|
+
* concreta: si entrara en la búsqueda por cercanía, los hex de marca ámbar/oliva de
|
|
20068
|
+
* cualquier negocio cambiarían de pack (y con él su secundario y sus estados) sin
|
|
20069
|
+
* haberlo elegido nadie.
|
|
20070
|
+
*/
|
|
20071
|
+
const EXACT_MATCH_ONLY = new Set(["amberYellow"]);
|
|
20072
|
+
const NEAREST_CANDIDATES = THEME_COLORS.filter((themeColor) => !EXACT_MATCH_ONLY.has(themeColor));
|
|
19152
20073
|
function isHexColor(value) {
|
|
19153
20074
|
return /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(value);
|
|
19154
20075
|
}
|
|
@@ -19165,7 +20086,7 @@ function hexToThemeColor(hex) {
|
|
|
19165
20086
|
const targetRgb = hexToRgb$1(hex);
|
|
19166
20087
|
let closest = "blue";
|
|
19167
20088
|
let minDistance = Number.POSITIVE_INFINITY;
|
|
19168
|
-
for (const themeColor of
|
|
20089
|
+
for (const themeColor of NEAREST_CANDIDATES) {
|
|
19169
20090
|
const themeRgb = hexToRgb$1(THEME_COLOR_HEX_MAP[themeColor]);
|
|
19170
20091
|
const dist = colorDistance(targetRgb, themeRgb);
|
|
19171
20092
|
if (dist < minDistance) {
|
|
@@ -19223,7 +20144,7 @@ function hslToCssValue(h, s, l) {
|
|
|
19223
20144
|
* Pasa un hex (`#rgb` o `#rrggbb`, en cualquier caja) a canales HSL.
|
|
19224
20145
|
*
|
|
19225
20146
|
* Se expone porque el hex es una de las dos formas en las que llega el `primary` del
|
|
19226
|
-
* tema —los
|
|
20147
|
+
* tema —los 16 packs lo emiten así en `theme-tokens.generated.css`— y `linda-tones.ts`
|
|
19227
20148
|
* necesita esa misma conversión para derivar los tonos del aura. Antes de exportarla ya
|
|
19228
20149
|
* había dos copias privadas de `hexToRgb` en esta carpeta; no hacía falta una tercera.
|
|
19229
20150
|
*/
|
|
@@ -19236,6 +20157,93 @@ function getContrastForeground(hex) {
|
|
|
19236
20157
|
const luminance = (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255;
|
|
19237
20158
|
return luminance > 0.5 ? "0 0% 0%" : "0 0% 100%";
|
|
19238
20159
|
}
|
|
20160
|
+
/** Contraste mínimo (WCAG) del texto de marca sobre el fondo suave de la propia marca. */
|
|
20161
|
+
const ACCENT_SOFT_FOREGROUND_MIN_CONTRAST = 3;
|
|
20162
|
+
/**
|
|
20163
|
+
* Opacidad del fondo tintado más oscuro sobre el que se pinta el token en modo claro: el
|
|
20164
|
+
* `flatBg` del Chip (accent al 20 % sobre blanco). El `--accent-soft` de HeroUI v3 en claro es
|
|
20165
|
+
* más claro (15 %), así que lo que llega aquí llega también en el Button soft.
|
|
20166
|
+
*/
|
|
20167
|
+
const SOFT_TINT_ALPHA = 0.2;
|
|
20168
|
+
/**
|
|
20169
|
+
* Proporción de `--accent` en la mezcla que trae HeroUI v3 en modo claro para
|
|
20170
|
+
* `--accent-soft-foreground`: `color-mix(in oklab, var(--accent) 70%, var(--foreground) 30%)`
|
|
20171
|
+
* (bloque `:root, .light, .default` de `@heroui/styles/dist/themes/default/variables.css`).
|
|
20172
|
+
*/
|
|
20173
|
+
const V3_LIGHT_ACCENT_SOFT_FOREGROUND_SHARE = 70;
|
|
20174
|
+
/** `--foreground` de HeroUI v3 en modo claro (`--eclipse`, oklch(0.2103 0.0059 285.89)). */
|
|
20175
|
+
const LIGHT_FOREGROUND_HEX = "#18181b";
|
|
20176
|
+
const toLinear = (c) => {
|
|
20177
|
+
const v = c / 255;
|
|
20178
|
+
return v <= 0.04045 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4;
|
|
20179
|
+
};
|
|
20180
|
+
const fromLinear = (c) => {
|
|
20181
|
+
const v = c <= 0.0031308 ? 12.92 * c : 1.055 * c ** (1 / 2.4) - 0.055;
|
|
20182
|
+
return Math.round(Math.min(Math.max(v, 0), 1) * 255);
|
|
20183
|
+
};
|
|
20184
|
+
function relativeLuminance([r, g, b]) {
|
|
20185
|
+
return 0.2126 * toLinear(r) + 0.7152 * toLinear(g) + 0.0722 * toLinear(b);
|
|
20186
|
+
}
|
|
20187
|
+
function contrastRatio(a, b) {
|
|
20188
|
+
const la = relativeLuminance(a);
|
|
20189
|
+
const lb = relativeLuminance(b);
|
|
20190
|
+
return (Math.max(la, lb) + 0.05) / (Math.min(la, lb) + 0.05);
|
|
20191
|
+
}
|
|
20192
|
+
function rgbToOklab([r, g, b]) {
|
|
20193
|
+
const [lr, lg, lb] = [toLinear(r), toLinear(g), toLinear(b)];
|
|
20194
|
+
const l = Math.cbrt(0.4122214708 * lr + 0.5363325363 * lg + 0.0514459929 * lb);
|
|
20195
|
+
const m = Math.cbrt(0.2119034982 * lr + 0.6806995451 * lg + 0.1073969566 * lb);
|
|
20196
|
+
const s = Math.cbrt(0.0883024619 * lr + 0.2817188376 * lg + 0.6299787005 * lb);
|
|
20197
|
+
return [
|
|
20198
|
+
0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s,
|
|
20199
|
+
1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s,
|
|
20200
|
+
0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s,
|
|
20201
|
+
];
|
|
20202
|
+
}
|
|
20203
|
+
function oklabToRgb([L, a, b]) {
|
|
20204
|
+
const l = (L + 0.3963377774 * a + 0.2158037573 * b) ** 3;
|
|
20205
|
+
const m = (L - 0.1055613458 * a - 0.0638541728 * b) ** 3;
|
|
20206
|
+
const s = (L - 0.0894841775 * a - 1.291485548 * b) ** 3;
|
|
20207
|
+
return [
|
|
20208
|
+
fromLinear(4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s),
|
|
20209
|
+
fromLinear(-1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s),
|
|
20210
|
+
fromLinear(-0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s),
|
|
20211
|
+
];
|
|
20212
|
+
}
|
|
20213
|
+
/** `color-mix(in oklab, accent share, foreground resto)` calculado en sRGB. */
|
|
20214
|
+
function mixOklab(accent, foreground, share) {
|
|
20215
|
+
const A = rgbToOklab(accent);
|
|
20216
|
+
const F = rgbToOklab(foreground);
|
|
20217
|
+
return oklabToRgb([0, 1, 2].map((i) => A[i] * share + F[i] * (1 - share)));
|
|
20218
|
+
}
|
|
20219
|
+
/**
|
|
20220
|
+
* Proporción de `--accent` (0–100) con la que `--accent-soft-foreground` alcanza
|
|
20221
|
+
* `minContrast` sobre su fondo tintado (el accent al 20 % sobre blanco), en modo claro.
|
|
20222
|
+
*
|
|
20223
|
+
* Devuelve `null` cuando la mezcla 70/30 que ya trae HeroUI v3 llega al mínimo: en esos
|
|
20224
|
+
* temas no se pisa nada. Si no llega, la primera proporción que sí lo hace, bajando de 1 en 1
|
|
20225
|
+
* (cuanto menos accent, más se acerca al color de texto). En el límite, 0: el propio
|
|
20226
|
+
* `--foreground`.
|
|
20227
|
+
*/
|
|
20228
|
+
function getAccentSoftForegroundShare(accentHex, minContrast = ACCENT_SOFT_FOREGROUND_MIN_CONTRAST) {
|
|
20229
|
+
const accent = hexToRgb(accentHex);
|
|
20230
|
+
const foreground = hexToRgb(LIGHT_FOREGROUND_HEX);
|
|
20231
|
+
const tint = accent.map((c) => c * SOFT_TINT_ALPHA + 255 * (1 - SOFT_TINT_ALPHA));
|
|
20232
|
+
const reaches = (share) => contrastRatio(mixOklab(accent, foreground, share), tint) >= minContrast;
|
|
20233
|
+
if (reaches(V3_LIGHT_ACCENT_SOFT_FOREGROUND_SHARE / 100)) {
|
|
20234
|
+
return null;
|
|
20235
|
+
}
|
|
20236
|
+
for (let share = V3_LIGHT_ACCENT_SOFT_FOREGROUND_SHARE - 1; share > 0; share--) {
|
|
20237
|
+
if (reaches(share / 100)) {
|
|
20238
|
+
return share;
|
|
20239
|
+
}
|
|
20240
|
+
}
|
|
20241
|
+
return 0;
|
|
20242
|
+
}
|
|
20243
|
+
/** Valor CSS de `--accent-soft-foreground` para una proporción de accent dada. */
|
|
20244
|
+
function accentSoftForegroundMix(share) {
|
|
20245
|
+
return `color-mix(in oklab, var(--accent) ${share}%, var(--foreground))`;
|
|
20246
|
+
}
|
|
19239
20247
|
const LIGHT_SHADE_LIGHTNESS = {
|
|
19240
20248
|
"50": 95,
|
|
19241
20249
|
"100": 90,
|
|
@@ -19284,6 +20292,8 @@ function generateThemeColorScale(hex, mode) {
|
|
|
19284
20292
|
return { shades, foreground, defaultValue };
|
|
19285
20293
|
}
|
|
19286
20294
|
|
|
20295
|
+
/** La mezcla que trae HeroUI v3 para `--accent-soft-foreground` en modo claro. */
|
|
20296
|
+
const V3_ACCENT_SOFT_FOREGROUND = "color-mix(in oklab, var(--accent) 70%, var(--foreground) 30%)";
|
|
19287
20297
|
const PRIMARY_SHADES = [
|
|
19288
20298
|
"50",
|
|
19289
20299
|
"100",
|
|
@@ -19303,6 +20313,7 @@ const CUSTOM_PROPERTIES = [
|
|
|
19303
20313
|
"--color-focus",
|
|
19304
20314
|
"--accent",
|
|
19305
20315
|
"--accent-foreground",
|
|
20316
|
+
"--accent-soft-foreground",
|
|
19306
20317
|
];
|
|
19307
20318
|
/**
|
|
19308
20319
|
* `generateThemeColorScale` devuelve canales HSL sueltos (`"212 100% 46.67%"`), que es lo que
|
|
@@ -19332,6 +20343,16 @@ function applyCustomPrimaryColor(hex, mode) {
|
|
|
19332
20343
|
style.setProperty("--color-focus", primary);
|
|
19333
20344
|
style.setProperty("--accent", primary);
|
|
19334
20345
|
style.setProperty("--accent-foreground", primaryForeground);
|
|
20346
|
+
// Mismo cálculo que los packs (generate-theme-tokens.mjs). Se escribe SIEMPRE en línea,
|
|
20347
|
+
// también cuando basta la mezcla de v3: la clase del pack más cercano puede traer su propia
|
|
20348
|
+
// proporción, calculada para SU color, y aquí manda el de la marca.
|
|
20349
|
+
// En oscuro no se pisa: vale la mezcla propia del tema oscuro de v3.
|
|
20350
|
+
if (mode === "dark") {
|
|
20351
|
+
style.removeProperty("--accent-soft-foreground");
|
|
20352
|
+
return;
|
|
20353
|
+
}
|
|
20354
|
+
const share = getAccentSoftForegroundShare(hex);
|
|
20355
|
+
style.setProperty("--accent-soft-foreground", share === null ? V3_ACCENT_SOFT_FOREGROUND : accentSoftForegroundMix(share));
|
|
19335
20356
|
}
|
|
19336
20357
|
function removeCustomPrimaryColor() {
|
|
19337
20358
|
const style = document.documentElement.style;
|
|
@@ -19837,6 +20858,7 @@ Object.defineProperty(exports, "loadIcons", {
|
|
|
19837
20858
|
enumerable: true,
|
|
19838
20859
|
get: function () { return react$1.loadIcons; }
|
|
19839
20860
|
});
|
|
20861
|
+
exports.ACCENT_SOFT_FOREGROUND_MIN_CONTRAST = ACCENT_SOFT_FOREGROUND_MIN_CONTRAST;
|
|
19840
20862
|
exports.ALL_THEMES = ALL_THEMES;
|
|
19841
20863
|
exports.AURORA_THEME_FAMILIES = AURORA_THEME_FAMILIES;
|
|
19842
20864
|
exports.AURORA_THEME_REGISTRY = AURORA_THEME_REGISTRY;
|
|
@@ -19856,6 +20878,11 @@ exports.BetaBadge = BetaBadge;
|
|
|
19856
20878
|
exports.BreadcrumbItem = BreadcrumbItem;
|
|
19857
20879
|
exports.BreadcrumbsComponent = BreadcrumbsComponent;
|
|
19858
20880
|
exports.Button = Button;
|
|
20881
|
+
exports.CHARACTER_CSS_VARS = CHARACTER_CSS_VARS;
|
|
20882
|
+
exports.CHARACTER_FIXED_COLORS = CHARACTER_FIXED_COLORS;
|
|
20883
|
+
exports.CHARACTER_THEMES = CHARACTER_THEMES;
|
|
20884
|
+
exports.CHARACTER_THEME_COLOR_KEYS = CHARACTER_THEME_COLOR_KEYS;
|
|
20885
|
+
exports.CHARACTER_THEME_IDS = CHARACTER_THEME_IDS;
|
|
19859
20886
|
exports.CONTAINER_ATTRIBUTE = CONTAINER_ATTRIBUTE;
|
|
19860
20887
|
exports.Card = Card;
|
|
19861
20888
|
exports.CardBody = CardBody;
|
|
@@ -19865,6 +20892,8 @@ exports.ColorPicker = ColorPicker;
|
|
|
19865
20892
|
exports.ColorSelector = ColorSelector;
|
|
19866
20893
|
exports.ContentCarousel = ContentCarousel;
|
|
19867
20894
|
exports.Currency = Currency;
|
|
20895
|
+
exports.DEFAULT_CHARACTER_PALETTE = DEFAULT_CHARACTER_PALETTE;
|
|
20896
|
+
exports.DEFAULT_CHARACTER_THEME_ID = DEFAULT_CHARACTER_THEME_ID;
|
|
19868
20897
|
exports.DEFAULT_DONUT_COLORS = DEFAULT_DONUT_COLORS;
|
|
19869
20898
|
exports.DEFAULT_PREDEFINED_COLORS = DEFAULT_PREDEFINED_COLORS;
|
|
19870
20899
|
exports.DEFAULT_RANKED_BAR_COLORS = DEFAULT_RANKED_BAR_COLORS;
|
|
@@ -19900,6 +20929,7 @@ exports.KanbanCard = KanbanCard;
|
|
|
19900
20929
|
exports.KanbanColumn = KanbanColumn;
|
|
19901
20930
|
exports.LINDA_MASCOT_LEVEL_VAR = LINDA_MASCOT_LEVEL_VAR;
|
|
19902
20931
|
exports.LINDA_MASCOT_STATES = LINDA_MASCOT_STATES;
|
|
20932
|
+
exports.LINDA_MASCOT_STATE_ALIASES = LINDA_MASCOT_STATE_ALIASES;
|
|
19903
20933
|
exports.LINDA_TONE_PROPERTIES = LINDA_TONE_PROPERTIES;
|
|
19904
20934
|
exports.LindaIcon = LindaIcon;
|
|
19905
20935
|
exports.LindaMascot = LindaMascot;
|
|
@@ -19915,6 +20945,7 @@ exports.NavigationLoadingContext = NavigationLoadingContext;
|
|
|
19915
20945
|
exports.NavigationLoadingOverlay = NavigationLoadingOverlay;
|
|
19916
20946
|
exports.NavigationLoadingProvider = NavigationLoadingProvider;
|
|
19917
20947
|
exports.P = P;
|
|
20948
|
+
exports.PLATFORM_THEME_TO_CHARACTER_THEME = PLATFORM_THEME_TO_CHARACTER_THEME;
|
|
19918
20949
|
exports.Pagination = Pagination;
|
|
19919
20950
|
exports.Phone = Phone;
|
|
19920
20951
|
exports.Progress = Progress;
|
|
@@ -19953,14 +20984,20 @@ exports.ToastContext = ToastContext;
|
|
|
19953
20984
|
exports.Tooltip = Tooltip;
|
|
19954
20985
|
exports.TwoColumnLayoutAgent = TwoColumnLayoutAgent;
|
|
19955
20986
|
exports.UploadFile = UploadFile;
|
|
20987
|
+
exports.V3_LIGHT_ACCENT_SOFT_FOREGROUND_SHARE = V3_LIGHT_ACCENT_SOFT_FOREGROUND_SHARE;
|
|
19956
20988
|
exports.VerticalSteps = VerticalSteps;
|
|
19957
20989
|
exports.ViolinPlot = ViolinPlot;
|
|
19958
20990
|
exports.WhatsAppPreview = WhatsAppPreview;
|
|
19959
20991
|
exports.Wizard = Wizard;
|
|
19960
20992
|
exports.WizardNavigation = WizardNavigation;
|
|
19961
20993
|
exports.WizardSidebar = WizardSidebar;
|
|
20994
|
+
exports.accentSoftForegroundMix = accentSoftForegroundMix;
|
|
20995
|
+
exports.applyCharacterPalette = applyCharacterPalette;
|
|
19962
20996
|
exports.applyCustomPrimaryColor = applyCustomPrimaryColor;
|
|
19963
20997
|
exports.applyLindaTones = applyLindaTones;
|
|
20998
|
+
exports.characterPaletteFromTheme = characterPaletteFromTheme;
|
|
20999
|
+
exports.characterPaletteToCssVars = characterPaletteToCssVars;
|
|
21000
|
+
exports.characterThemeForPlatformTheme = characterThemeForPlatformTheme;
|
|
19964
21001
|
exports.cn = cn;
|
|
19965
21002
|
exports.computeBars = computeBars;
|
|
19966
21003
|
exports.computeMax = computeMax;
|
|
@@ -19977,6 +21014,7 @@ exports.forceLightOnlyThemeBeforeReact = forceLightOnlyThemeBeforeReact;
|
|
|
19977
21014
|
exports.formatAuroraThemeTooltip = formatAuroraThemeTooltip;
|
|
19978
21015
|
exports.formatDonutPercent = formatDonutPercent;
|
|
19979
21016
|
exports.generateThemeColorScale = generateThemeColorScale;
|
|
21017
|
+
exports.getAccentSoftForegroundShare = getAccentSoftForegroundShare;
|
|
19980
21018
|
exports.getContrastForeground = getContrastForeground;
|
|
19981
21019
|
exports.getRegisteredThemeColorBases = getRegisteredThemeColorBases;
|
|
19982
21020
|
exports.getSelectedKeyFromPath = getSelectedKeyFromPath;
|
|
@@ -19984,6 +21022,7 @@ exports.hexToHsl = hexToHsl;
|
|
|
19984
21022
|
exports.hexToThemeColor = hexToThemeColor;
|
|
19985
21023
|
exports.hslToCssValue = hslToCssValue;
|
|
19986
21024
|
exports.isAuroraFullThemeId = isAuroraFullThemeId;
|
|
21025
|
+
exports.isCompleteCharacterPalette = isCompleteCharacterPalette;
|
|
19987
21026
|
exports.isDismissControl = isDismissControl;
|
|
19988
21027
|
exports.isDonutEmpty = isDonutEmpty;
|
|
19989
21028
|
exports.isExactThemeColor = isExactThemeColor;
|
|
@@ -19991,9 +21030,13 @@ exports.isGroupState = isGroupState;
|
|
|
19991
21030
|
exports.isHexColor = isHexColor;
|
|
19992
21031
|
exports.isRankedBarListEmpty = isRankedBarListEmpty;
|
|
19993
21032
|
exports.isSegmentationGroup = isSegmentationGroup;
|
|
21033
|
+
exports.normalizeCharacterPalette = normalizeCharacterPalette;
|
|
21034
|
+
exports.normalizeCharacterThemeColors = normalizeCharacterThemeColors;
|
|
19994
21035
|
exports.parseColorToHsl = parseColorToHsl;
|
|
21036
|
+
exports.removeCharacterPalette = removeCharacterPalette;
|
|
19995
21037
|
exports.removeCustomPrimaryColor = removeCustomPrimaryColor;
|
|
19996
21038
|
exports.removeLindaTones = removeLindaTones;
|
|
21039
|
+
exports.resolveMascotState = resolveMascotState;
|
|
19997
21040
|
exports.shouldClosePopoverOnInteractOutside = shouldClosePopoverOnInteractOutside;
|
|
19998
21041
|
exports.sizeMap = sizeMap;
|
|
19999
21042
|
exports.themeColors = themeColors;
|