@eduardoalvarez/arrecife 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/LICENSE +21 -0
  3. package/README.md +520 -0
  4. package/assets/brand/face-annoyed.png +0 -0
  5. package/assets/brand/face-confused.png +0 -0
  6. package/assets/brand/face-hearts.png +0 -0
  7. package/assets/brand/face-laughing.png +0 -0
  8. package/assets/brand/face-shades.png +0 -0
  9. package/assets/brand/face-waiting.png +0 -0
  10. package/assets/brand/face-wink.png +0 -0
  11. package/assets/brand/fin-foam.png +0 -0
  12. package/assets/brand/fin.png +0 -0
  13. package/assets/brand/pose-desk.png +0 -0
  14. package/assets/brand/pose-laptop-coffee.png +0 -0
  15. package/assets/brand/pose-peek.png +0 -0
  16. package/assets/brand/pose-surf.png +0 -0
  17. package/dist/brand/index.cjs +228 -0
  18. package/dist/brand/index.d.cts +63 -0
  19. package/dist/brand/index.d.ts +63 -0
  20. package/dist/brand/index.js +3 -0
  21. package/dist/catalogo-Du5ID-Hi.d.cts +77 -0
  22. package/dist/catalogo-Du5ID-Hi.d.ts +77 -0
  23. package/dist/chunk-22OXRTAL.js +22 -0
  24. package/dist/chunk-DHF63QNM.js +231 -0
  25. package/dist/chunk-E3OMP2DL.js +36 -0
  26. package/dist/chunk-ZL5X6XO7.js +102 -0
  27. package/dist/index.cjs +3191 -0
  28. package/dist/index.d.cts +1024 -0
  29. package/dist/index.d.ts +1024 -0
  30. package/dist/index.js +2624 -0
  31. package/dist/og/index.cjs +322 -0
  32. package/dist/og/index.d.cts +164 -0
  33. package/dist/og/index.d.ts +164 -0
  34. package/dist/og/index.js +242 -0
  35. package/dist/shiki/index.cjs +127 -0
  36. package/dist/shiki/index.d.cts +16 -0
  37. package/dist/shiki/index.d.ts +16 -0
  38. package/dist/shiki/index.js +95 -0
  39. package/dist/tokens/index.cjs +263 -0
  40. package/dist/tokens/index.d.cts +623 -0
  41. package/dist/tokens/index.d.ts +623 -0
  42. package/dist/tokens/index.js +2 -0
  43. package/dist/tokens/theme.css +266 -0
  44. package/package.json +128 -0
package/dist/index.cjs ADDED
@@ -0,0 +1,3191 @@
1
+ 'use strict';
2
+
3
+ var classVarianceAuthority = require('class-variance-authority');
4
+ var clsx = require('clsx');
5
+ var tailwindMerge = require('tailwind-merge');
6
+ var jsxRuntime = require('react/jsx-runtime');
7
+ var AvatarPrimitive = require('@radix-ui/react-avatar');
8
+ var reactSlot = require('@radix-ui/react-slot');
9
+ var locale = require('date-fns/locale');
10
+ var reactDayPicker = require('react-day-picker');
11
+ var CheckboxPrimitive = require('@radix-ui/react-checkbox');
12
+ var DialogPrimitive = require('@radix-ui/react-dialog');
13
+ var DropdownMenuPrimitive = require('@radix-ui/react-dropdown-menu');
14
+ var LabelPrimitive = require('@radix-ui/react-label');
15
+ var PopoverPrimitive = require('@radix-ui/react-popover');
16
+ var ProgressPrimitive = require('@radix-ui/react-progress');
17
+ var RadioGroupPrimitive = require('@radix-ui/react-radio-group');
18
+ var SelectPrimitive = require('@radix-ui/react-select');
19
+ var SeparatorPrimitive = require('@radix-ui/react-separator');
20
+ var SwitchPrimitive = require('@radix-ui/react-switch');
21
+ var TabsPrimitive = require('@radix-ui/react-tabs');
22
+ var ToastPrimitive = require('@radix-ui/react-toast');
23
+ var TooltipPrimitive = require('@radix-ui/react-tooltip');
24
+ var react = require('react');
25
+
26
+ function _interopNamespace(e) {
27
+ if (e && e.__esModule) return e;
28
+ var n = Object.create(null);
29
+ if (e) {
30
+ Object.keys(e).forEach(function (k) {
31
+ if (k !== 'default') {
32
+ var d = Object.getOwnPropertyDescriptor(e, k);
33
+ Object.defineProperty(n, k, d.get ? d : {
34
+ enumerable: true,
35
+ get: function () { return e[k]; }
36
+ });
37
+ }
38
+ });
39
+ }
40
+ n.default = e;
41
+ return Object.freeze(n);
42
+ }
43
+
44
+ var AvatarPrimitive__namespace = /*#__PURE__*/_interopNamespace(AvatarPrimitive);
45
+ var CheckboxPrimitive__namespace = /*#__PURE__*/_interopNamespace(CheckboxPrimitive);
46
+ var DialogPrimitive__namespace = /*#__PURE__*/_interopNamespace(DialogPrimitive);
47
+ var DropdownMenuPrimitive__namespace = /*#__PURE__*/_interopNamespace(DropdownMenuPrimitive);
48
+ var LabelPrimitive__namespace = /*#__PURE__*/_interopNamespace(LabelPrimitive);
49
+ var PopoverPrimitive__namespace = /*#__PURE__*/_interopNamespace(PopoverPrimitive);
50
+ var ProgressPrimitive__namespace = /*#__PURE__*/_interopNamespace(ProgressPrimitive);
51
+ var RadioGroupPrimitive__namespace = /*#__PURE__*/_interopNamespace(RadioGroupPrimitive);
52
+ var SelectPrimitive__namespace = /*#__PURE__*/_interopNamespace(SelectPrimitive);
53
+ var SeparatorPrimitive__namespace = /*#__PURE__*/_interopNamespace(SeparatorPrimitive);
54
+ var SwitchPrimitive__namespace = /*#__PURE__*/_interopNamespace(SwitchPrimitive);
55
+ var TabsPrimitive__namespace = /*#__PURE__*/_interopNamespace(TabsPrimitive);
56
+ var ToastPrimitive__namespace = /*#__PURE__*/_interopNamespace(ToastPrimitive);
57
+ var TooltipPrimitive__namespace = /*#__PURE__*/_interopNamespace(TooltipPrimitive);
58
+
59
+ var __defProp = Object.defineProperty;
60
+ var __export = (target, all) => {
61
+ for (var name in all)
62
+ __defProp(target, name, { get: all[name], enumerable: true });
63
+ };
64
+
65
+ // src/tokens/tokens.ts
66
+ var dark = {
67
+ background: "#091319",
68
+ // abismo · fondo de página
69
+ surface: "#10202B",
70
+ // fosa · tarjetas y paneles
71
+ surfaceRaised: "#17303E",
72
+ // corriente · menús, tabs activos
73
+ border: "#22414F",
74
+ // bordes de control
75
+ hairline: "#1E3441",
76
+ // divisiones sutiles
77
+ hairlineHover: "#2C4D5D",
78
+ // hairline en hover de tarjeta
79
+ textPrimary: "#EDF4F3",
80
+ // espuma 16.84:1
81
+ textSecondary: "#A7BCC4",
82
+ // bruma 9.50:1
83
+ textMuted: "#71919C",
84
+ // plancton 5.57:1 nunca bajo 13px
85
+ accent: "#35D6C0",
86
+ // bioluz 10.31:1 interactivo
87
+ accentHover: "#5FE3D1",
88
+ accentOn: "#06171A",
89
+ // tinta sobre bioluz
90
+ warm: "#F2A65A",
91
+ // arena 9.28:1 humano y conversión
92
+ warmHover: "#F7BB7D",
93
+ warmOn: "#2A1605",
94
+ // tinta sobre arena
95
+ success: "#4FB477",
96
+ warning: "#E8A33D",
97
+ error: "#E15757"
98
+ // 4.51:1 sobre surface
99
+ };
100
+ var light = {
101
+ background: "#F6F2EA",
102
+ // papel
103
+ surface: "#FFFFFF",
104
+ surfaceRaised: "#EFE9DE",
105
+ border: "#E6DFD2",
106
+ hairline: "#EBE6DC",
107
+ hairlineHover: "#D3C8B2",
108
+ // hairline en hover de tarjeta
109
+ textPrimary: "#0B1524",
110
+ // 16.40:1
111
+ textSecondary: "#3D4B58",
112
+ textMuted: "#626A75",
113
+ // 4.53:1 sobre surfaceRaised
114
+ accent: "#0D7C6F",
115
+ // bioluz oscura 4.55:1
116
+ accentHover: "#0C7466",
117
+ accentOn: "#FFFFFF",
118
+ warm: "#A65B27",
119
+ // arena oscura 4.54:1
120
+ warmHover: "#96511F",
121
+ warmOn: "#FFF7EE",
122
+ success: "#0F6B52",
123
+ warning: "#8D6111",
124
+ // 4.51:1 sobre surfaceRaised
125
+ error: "#C0392B"
126
+ };
127
+ var colors = { dark, light };
128
+ var brand = {
129
+ /** Cuerpo de la mascota. 4.22:1 → SOLO relleno, NUNCA texto. */
130
+ body: "#3E7CB1",
131
+ /** Patrón de manchas. */
132
+ spots: "#C2D7E7",
133
+ /** Casco · contorno y fondo de bloques de código. */
134
+ hull: "#0B1524"
135
+ };
136
+ var fonts = {
137
+ /** SOLO titulares y números grandes. Nunca cuerpo. */
138
+ display: '"Bricolage Grotesque", ui-sans-serif, system-ui, sans-serif',
139
+ /** Cuerpo e interfaz. */
140
+ sans: '"Geist", ui-sans-serif, system-ui, sans-serif',
141
+ /** Código, rutas, etiquetas, metadatos, firma CLI. */
142
+ mono: '"JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace'
143
+ };
144
+ var typeScale = {
145
+ display: { family: "display", size: 76, lineHeight: 0.96, weight: 800, tracking: "-0.035em" },
146
+ /** Métricas grandes. Números, no prosa: interlineado 1 y sin descendentes. */
147
+ stat: { family: "display", size: 46, lineHeight: 1, weight: 800, tracking: "-0.035em" },
148
+ h1: { family: "display", size: 44, lineHeight: 1.05, weight: 700, tracking: "-0.03em" },
149
+ h2: { family: "display", size: 30, lineHeight: 1.1, weight: 600, tracking: "-0.02em" },
150
+ h3: { family: "display", size: 25, lineHeight: 1.15, weight: 600, tracking: "-0.02em" },
151
+ body: { family: "sans", size: 18, lineHeight: 1.75, weight: 400 },
152
+ /**
153
+ * 17px. El botón grande y la bajada de las páginas internas.
154
+ *
155
+ * Entra como escalón propio porque el documento lo usa DOS veces y en piezas
156
+ * distintas: «lg 15px 30px r12» con texto de 17, y «h1 44/700 · bajada 17px ·
157
+ * párrafo de contexto 15px». Un solo uso no habría justificado partir la
158
+ * distancia entre `ui` (15) y `body` (18); dos sí.
159
+ */
160
+ lead: { family: "sans", size: 17, lineHeight: 1.5, weight: 400 },
161
+ ui: { family: "sans", size: 15, lineHeight: 1.6, weight: 400 },
162
+ label: { family: "sans", size: 13, lineHeight: 1.5, weight: 500 },
163
+ /**
164
+ * La escala de las etiquetas de estado: sans 12.5/500, cuadrada.
165
+ *
166
+ * Es medio píxel por debajo de `label`, y esta vez el medio píxel sí importa:
167
+ * una etiqueta de estado va dentro de una tabla o al lado de un título, y a 13
168
+ * competía con el texto que acompaña. El documento la da en 12.5 y se ve.
169
+ */
170
+ tag: { family: "sans", size: 12.5, lineHeight: 1.4, weight: 500 },
171
+ /**
172
+ * La escala de categoría y métrica: mono 11.5.
173
+ *
174
+ * Rompe el suelo de `limits.minScreenPx`, y es a propósito. Ese suelo protege
175
+ * al TEXTO —lo que se lee en una frase—, y una píldora de una palabra no es
176
+ * texto corrido: es una marca. El contraste sigue medido y pasa AA (plancton
177
+ * 5.57:1 sobre abismo), que es la parte que no se negocia.
178
+ *
179
+ * A 13 las tres familias de etiqueta salían del tamaño de un botón pequeño y
180
+ * pesaban más que el título que acompañan. Ver `docs/decisiones.md`.
181
+ */
182
+ chip: { family: "mono", size: 11.5, lineHeight: 1.4, weight: 400 },
183
+ /**
184
+ * Mono SIN transformar: fechas, rutas, versiones, nombres de archivo, la firma
185
+ * del footer y las métricas de etiqueta. Es la mayoría del mono del sistema.
186
+ *
187
+ * Existe porque `eyebrow` lleva `uppercase` de fábrica y no es una preferencia
188
+ * que se pueda apagar: es la escala del eyebrow. Un `18 ago 2026` en versalitas
189
+ * o un `pose-laptop-coffee.png` en mayúsculas están mal, y sin este escalón la
190
+ * única salida era un `normal-case` en cada sitio de uso.
191
+ *
192
+ * El documento dice 12.5. Son 13 por la misma razón por la que `textMuted` se
193
+ * corrigió: `limits.minScreenPx` es 13 y plancton «nunca bajo 13px». Esta
194
+ * escala es justo donde se escriben las metas en muted, así que ponerla en
195
+ * 12.5 habría dejado ilegible su uso más común por medio píxel.
196
+ */
197
+ meta: { family: "mono", size: 13, lineHeight: 1.6, weight: 400 },
198
+ eyebrow: { family: "mono", size: 12, tracking: "0.12em", transform: "uppercase" }
199
+ };
200
+ var limits = {
201
+ /** Mínimo absoluto en pantalla. */
202
+ minScreenPx: 13,
203
+ /** Mínimo absoluto impreso. */
204
+ minPrintPt: 12,
205
+ /** Medida máxima de cuerpo. */
206
+ measure: "68ch"
207
+ };
208
+ var radius = {
209
+ chip: 6,
210
+ control: 10,
211
+ card: 14,
212
+ panel: 16,
213
+ pill: 999
214
+ };
215
+ var control = {
216
+ sm: 14,
217
+ md: 22,
218
+ lg: 30,
219
+ /** Botón de icono: cuadrado, sin texto. */
220
+ icon: 42
221
+ };
222
+ var spacing = {
223
+ xs: 8,
224
+ sm: 12,
225
+ md: 16,
226
+ lg: 26,
227
+ xl: 40,
228
+ section: 96
229
+ };
230
+ var size = {
231
+ /** Alto de la barra de navegación. */
232
+ nav: 64,
233
+ /** Ancho de columna de lectura. */
234
+ content: 760,
235
+ /** Ancho máximo de página. */
236
+ wide: 1180
237
+ };
238
+ var sintaxis = {
239
+ /** El casco. Es el fondo del bloque en los dos modos. */
240
+ fondo: brand.hull,
241
+ /** Identificadores, funciones, tipos, variables. */
242
+ identificador: dark.textPrimary,
243
+ /** Cadenas, números, booleanos, null. */
244
+ literal: dark.accent,
245
+ /** Palabras clave, control de flujo, `import`, `this`. */
246
+ palabraClave: dark.warm,
247
+ /** Comentarios y puntuación. */
248
+ comentario: dark.textMuted,
249
+ /** `markup.deleted`, `invalid`. */
250
+ invalido: dark.error
251
+ };
252
+ var profundo = "#0D2129";
253
+ var gradient = {
254
+ dark: {
255
+ hero: `linear-gradient(160deg, ${dark.background} 60%, ${profundo} 100%)`,
256
+ seccion: `linear-gradient(150deg, ${dark.surface} 0%, ${profundo} 100%)`,
257
+ /** El de la plantilla OG de artículo. 145°, del documento. */
258
+ og: `linear-gradient(145deg, ${dark.background} 55%, ${profundo} 100%)`
259
+ },
260
+ light: {
261
+ hero: `linear-gradient(160deg, ${light.background} 60%, ${light.surfaceRaised} 100%)`,
262
+ seccion: `linear-gradient(150deg, ${light.surface} 0%, ${light.surfaceRaised} 100%)`,
263
+ og: `linear-gradient(145deg, ${light.background} 55%, ${light.surfaceRaised} 100%)`
264
+ }
265
+ };
266
+ var shadow = {
267
+ standard: "0 1px 2px rgba(0, 0, 0, 0.35)"
268
+ };
269
+ var motion = {
270
+ duration: "150ms",
271
+ easing: "ease-out",
272
+ properties: "color, background-color, border-color, fill, stroke"
273
+ };
274
+ var tagline = {
275
+ /** Hero. */
276
+ largo: "Ayudo a equipos de ingenier\xEDa a escalar con criterio",
277
+ /** Header, una línea. */
278
+ corto: "Ayudo a equipos a escalar con criterio",
279
+ /** LinkedIn. */
280
+ en: "Helping engineering teams scale with judgment"
281
+ };
282
+ var naming = {
283
+ wordmark: "Eduardo \xC1lvarez",
284
+ mascot: "Tiburonc\xEDn",
285
+ /** El dominio, para la firma CLI del footer: `$ cd ~/eduardoalvarez.dev/2026`. */
286
+ domain: "eduardoalvarez.dev"
287
+ };
288
+
289
+ // src/tokens/index.ts
290
+ var tokens = {
291
+ colors,
292
+ brand,
293
+ fonts,
294
+ typeScale,
295
+ limits,
296
+ radius,
297
+ control,
298
+ spacing,
299
+ size,
300
+ gradient,
301
+ sintaxis,
302
+ shadow,
303
+ motion,
304
+ tagline,
305
+ naming
306
+ };
307
+ var escalas = Object.keys(typeScale);
308
+ var radios = Object.keys(radius);
309
+ var espacios = Object.keys(spacing);
310
+ var controles = Object.keys(control).map((nombre) => `control-${nombre}`);
311
+ var twMerge = tailwindMerge.extendTailwindMerge({
312
+ extend: {
313
+ classGroups: {
314
+ "font-size": [{ text: escalas }],
315
+ rounded: [{ rounded: radios }],
316
+ p: [{ p: espacios }],
317
+ px: [{ px: [...espacios, ...controles] }],
318
+ py: [{ py: espacios }],
319
+ gap: [{ gap: espacios }],
320
+ size: [{ size: controles }]
321
+ }
322
+ }
323
+ });
324
+ function cn(...inputs) {
325
+ return twMerge(clsx.clsx(inputs));
326
+ }
327
+ var alert = classVarianceAuthority.cva("w-full rounded-card border p-md font-sans text-ui", {
328
+ variants: {
329
+ variant: {
330
+ accent: "text-text-secondary",
331
+ success: "text-text-secondary",
332
+ warning: "text-text-secondary",
333
+ error: "text-text-secondary"
334
+ },
335
+ enfasis: {
336
+ sutil: "",
337
+ fuerte: ""
338
+ }
339
+ },
340
+ compoundVariants: [
341
+ { variant: "accent", enfasis: "sutil", class: "border-accent/22 bg-accent/8" },
342
+ { variant: "success", enfasis: "sutil", class: "border-success/22 bg-success/8" },
343
+ { variant: "warning", enfasis: "sutil", class: "border-warning/22 bg-warning/8" },
344
+ { variant: "error", enfasis: "sutil", class: "border-error/22 bg-error/8" },
345
+ { variant: "accent", enfasis: "fuerte", class: "border-accent bg-accent/10" },
346
+ { variant: "success", enfasis: "fuerte", class: "border-success bg-success/10" },
347
+ { variant: "warning", enfasis: "fuerte", class: "border-warning bg-warning/10" },
348
+ { variant: "error", enfasis: "fuerte", class: "border-error bg-error/10" }
349
+ ],
350
+ defaultVariants: { variant: "accent", enfasis: "sutil" }
351
+ });
352
+ var glifoColor = {
353
+ accent: "text-accent",
354
+ success: "text-success",
355
+ warning: "text-warning",
356
+ error: "text-error"
357
+ };
358
+ var GLIFO = {
359
+ accent: "\u2726",
360
+ success: "\u2713",
361
+ warning: "!",
362
+ error: "\u2715"
363
+ };
364
+ function Alert({
365
+ className,
366
+ variant,
367
+ enfasis,
368
+ title,
369
+ icon,
370
+ children,
371
+ ...props
372
+ }) {
373
+ const tono = variant ?? "accent";
374
+ return /* @__PURE__ */ jsxRuntime.jsx(
375
+ "div",
376
+ {
377
+ role: tono === "error" ? "alert" : "status",
378
+ className: cn(alert({ variant, enfasis }), className),
379
+ ...props,
380
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "gap-sm flex items-start", children: [
381
+ /* @__PURE__ */ jsxRuntime.jsx(
382
+ "span",
383
+ {
384
+ "aria-hidden": "true",
385
+ className: cn("font-mono text-ui leading-normal select-none", glifoColor[tono]),
386
+ children: icon ?? GLIFO[tono]
387
+ }
388
+ ),
389
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
390
+ title ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-xs text-text-primary font-medium", children: title }) : null,
391
+ children ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-measure", children }) : null
392
+ ] })
393
+ ] })
394
+ }
395
+ );
396
+ }
397
+ var avatar = classVarianceAuthority.cva(
398
+ "relative flex shrink-0 overflow-hidden rounded-pill bg-surface-raised border border-hairline",
399
+ {
400
+ variants: {
401
+ size: {
402
+ sm: "size-8",
403
+ md: "size-10",
404
+ lg: "size-14",
405
+ xl: "size-24"
406
+ }
407
+ },
408
+ defaultVariants: { size: "md" }
409
+ }
410
+ );
411
+ function Avatar({ className, size: size2, ...props }) {
412
+ return /* @__PURE__ */ jsxRuntime.jsx(AvatarPrimitive__namespace.Root, { className: cn(avatar({ size: size2 }), className), ...props });
413
+ }
414
+ function AvatarImage({
415
+ className,
416
+ ...props
417
+ }) {
418
+ return /* @__PURE__ */ jsxRuntime.jsx(AvatarPrimitive__namespace.Image, { className: cn("aspect-square size-full object-cover", className), ...props });
419
+ }
420
+ function AvatarFallback({
421
+ className,
422
+ ...props
423
+ }) {
424
+ return /* @__PURE__ */ jsxRuntime.jsx(
425
+ AvatarPrimitive__namespace.Fallback,
426
+ {
427
+ className: cn(
428
+ "text-label font-mono text-text-secondary flex size-full items-center justify-center uppercase",
429
+ className
430
+ ),
431
+ ...props
432
+ }
433
+ );
434
+ }
435
+ var badge = classVarianceAuthority.cva(
436
+ ["inline-flex items-center gap-xs", "rounded-chip px-xs py-0.5", "font-sans text-tag", "transition-standard"],
437
+ {
438
+ variants: {
439
+ variant: {
440
+ neutral: "bg-surface-raised text-text-secondary",
441
+ accent: "bg-accent/8 text-text-primary",
442
+ warm: "bg-warm/8 text-text-primary",
443
+ success: "bg-success/8 text-text-primary",
444
+ warning: "bg-warning/8 text-text-primary",
445
+ error: "bg-error/8 text-text-primary"
446
+ }
447
+ },
448
+ defaultVariants: { variant: "neutral" }
449
+ }
450
+ );
451
+ function Badge({ className, variant, ...props }) {
452
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(badge({ variant }), className), ...props });
453
+ }
454
+ var categoria = classVarianceAuthority.cva(
455
+ [
456
+ "inline-flex items-center gap-xs",
457
+ "rounded-pill px-sm py-0.5",
458
+ "font-mono text-chip",
459
+ "border transition-standard"
460
+ ],
461
+ {
462
+ variants: {
463
+ active: {
464
+ false: "border-warm/28 bg-transparent text-warm",
465
+ true: "border-warm bg-warm text-warm-on"
466
+ }
467
+ },
468
+ defaultVariants: { active: false }
469
+ }
470
+ );
471
+ function CategoryBadge({ className, active = false, ...props }) {
472
+ return /* @__PURE__ */ jsxRuntime.jsx(
473
+ "span",
474
+ {
475
+ "data-active": active || void 0,
476
+ className: cn(categoria({ active }), className),
477
+ ...props
478
+ }
479
+ );
480
+ }
481
+ var metrica = ["inline-flex items-center gap-xs", "rounded-pill", "font-mono text-chip text-text-muted"];
482
+ function MetricBadge({ className, boxed = false, ...props }) {
483
+ return /* @__PURE__ */ jsxRuntime.jsx(
484
+ "span",
485
+ {
486
+ className: cn(metrica, boxed && "border-hairline px-sm py-0.5 border", className),
487
+ ...props
488
+ }
489
+ );
490
+ }
491
+ function Glyph({ children, ...props }) {
492
+ return /* @__PURE__ */ jsxRuntime.jsx(
493
+ "svg",
494
+ {
495
+ viewBox: "0 0 16 16",
496
+ width: "1em",
497
+ height: "1em",
498
+ fill: "none",
499
+ stroke: "currentColor",
500
+ strokeWidth: 1.75,
501
+ strokeLinecap: "round",
502
+ strokeLinejoin: "round",
503
+ "aria-hidden": "true",
504
+ focusable: "false",
505
+ ...props,
506
+ children
507
+ }
508
+ );
509
+ }
510
+ var Check = (props) => /* @__PURE__ */ jsxRuntime.jsx(Glyph, { ...props, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3 8.5 6.5 12 13 4.5" }) });
511
+ var Minus = (props) => /* @__PURE__ */ jsxRuntime.jsx(Glyph, { ...props, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3.5 8h9" }) });
512
+ var ChevronDown = (props) => /* @__PURE__ */ jsxRuntime.jsx(Glyph, { ...props, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M4 6l4 4 4-4" }) });
513
+ var ChevronUp = (props) => /* @__PURE__ */ jsxRuntime.jsx(Glyph, { ...props, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M4 10l4-4 4 4" }) });
514
+ var ChevronLeft = (props) => /* @__PURE__ */ jsxRuntime.jsx(Glyph, { ...props, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10 4L6 8l4 4" }) });
515
+ var ChevronRight = (props) => /* @__PURE__ */ jsxRuntime.jsx(Glyph, { ...props, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 4l4 4-4 4" }) });
516
+ var Close = (props) => /* @__PURE__ */ jsxRuntime.jsx(Glyph, { ...props, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M4 4l8 8M12 4l-8 8" }) });
517
+ var Copy = (props) => /* @__PURE__ */ jsxRuntime.jsxs(Glyph, { ...props, children: [
518
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "5.5", y: "5.5", width: "8", height: "8", rx: "1.5" }),
519
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10.5 3.5h-7a1.5 1.5 0 0 0-1.5 1.5v7" })
520
+ ] });
521
+ var ArrowUpRight = (props) => /* @__PURE__ */ jsxRuntime.jsx(Glyph, { ...props, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 11l6-6M5.5 5h5.5v5.5" }) });
522
+ var Ellipsis = (props) => /* @__PURE__ */ jsxRuntime.jsx(Glyph, { ...props, strokeWidth: 2.25, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M4 8h.01M8 8h.01M12 8h.01" }) });
523
+ var Spinner = (props) => /* @__PURE__ */ jsxRuntime.jsxs(
524
+ "svg",
525
+ {
526
+ viewBox: "0 0 16 16",
527
+ width: "1em",
528
+ height: "1em",
529
+ fill: "none",
530
+ stroke: "currentColor",
531
+ strokeWidth: 2,
532
+ strokeLinecap: "round",
533
+ "aria-hidden": "true",
534
+ focusable: "false",
535
+ className: "motion-safe:animate-spin",
536
+ ...props,
537
+ children: [
538
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "8", cy: "8", r: "6", opacity: 0.3 }),
539
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 2a6 6 0 0 1 6 6" })
540
+ ]
541
+ }
542
+ );
543
+ function GlifoMedia({ children, ...props }) {
544
+ return /* @__PURE__ */ jsxRuntime.jsx(
545
+ "svg",
546
+ {
547
+ xmlns: "http://www.w3.org/2000/svg",
548
+ viewBox: "0 0 24 24",
549
+ fill: "none",
550
+ "aria-hidden": "true",
551
+ focusable: "false",
552
+ ...props,
553
+ children
554
+ }
555
+ );
556
+ }
557
+ var Play = (props) => /* @__PURE__ */ jsxRuntime.jsx(GlifoMedia, { fill: "currentColor", ...props, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 5v14l11-7z" }) });
558
+ var Pause = (props) => /* @__PURE__ */ jsxRuntime.jsx(GlifoMedia, { fill: "currentColor", ...props, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 4h4v16H6V4zm8 0h4v16h-4V4z" }) });
559
+ var Retry = (props) => /* @__PURE__ */ jsxRuntime.jsx(
560
+ GlifoMedia,
561
+ {
562
+ stroke: "currentColor",
563
+ strokeWidth: 2,
564
+ strokeLinecap: "round",
565
+ strokeLinejoin: "round",
566
+ ...props,
567
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" })
568
+ }
569
+ );
570
+ var GoBackSeconds = (props) => /* @__PURE__ */ jsxRuntime.jsxs(GlifoMedia, { stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round", ...props, children: [
571
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M16.5 8.5H13.8604C13.6452 8.5 13.4541 8.63772 13.386 8.84189L12.7194 10.8419C12.6114 11.1657 12.8524 11.5 13.1937 11.5H14.5C15.6046 11.5 16.5 12.3954 16.5 13.5C16.5 14.6046 15.6046 15.5 14.5 15.5H12.5" }),
572
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M7.5 10.5L10 8.5V15.5", strokeLinejoin: "round" }),
573
+ /* @__PURE__ */ jsxRuntime.jsx(
574
+ "path",
575
+ {
576
+ d: "M14 4.5L12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22C8.7288 22 5.82446 20.4293 4 18.001M8 2.83209C6.87754 3.32251 5.86251 4.01303 5 4.85857C3.14864 6.67349 2 9.20261 2 12C2 12.6849 2.06886 13.3538 2.20004 14",
577
+ strokeLinejoin: "round"
578
+ }
579
+ )
580
+ ] });
581
+ var AdvanceSeconds = (props) => /* @__PURE__ */ jsxRuntime.jsxs(GlifoMedia, { stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round", ...props, children: [
582
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M16.5 8.5H13.8604C13.6452 8.5 13.4541 8.63772 13.386 8.84189L12.7194 10.8419C12.6114 11.1657 12.8524 11.5 13.1937 11.5H14.5C15.6046 11.5 16.5 12.3954 16.5 13.5C16.5 14.6046 15.6046 15.5 14.5 15.5H12.5" }),
583
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M7.5 10.5L10 8.5V15.5", strokeLinejoin: "round" }),
584
+ /* @__PURE__ */ jsxRuntime.jsx(
585
+ "path",
586
+ {
587
+ d: "M10 4.5L12 2C6.47715 2 2 6.47715 2 12C2 12.6849 2.06886 13.3538 2.20004 14M16 2.83209C19.5318 4.3752 22 7.89936 22 12C22 17.5228 17.5228 22 12 22C8.72852 22 5.82443 20.4287 4 18",
588
+ strokeLinejoin: "round"
589
+ }
590
+ )
591
+ ] });
592
+ var VolumeOn = (props) => /* @__PURE__ */ jsxRuntime.jsx(GlifoMedia, { fill: "currentColor", ...props, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z" }) });
593
+ var VolumeMuted = (props) => /* @__PURE__ */ jsxRuntime.jsx(GlifoMedia, { fill: "currentColor", ...props, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C20.63 14.91 21 13.5 21 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3L3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06c1.38-.31 2.63-.95 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4L9.91 6.09 12 8.18V4z" }) });
594
+ var button = classVarianceAuthority.cva(
595
+ [
596
+ "inline-flex cursor-pointer items-center justify-center gap-xs whitespace-nowrap select-none",
597
+ "rounded-control font-sans font-medium",
598
+ "transition-standard",
599
+ "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent",
600
+ "disabled:pointer-events-none disabled:opacity-50",
601
+ "[&_svg]:shrink-0"
602
+ ],
603
+ {
604
+ variants: {
605
+ variant: {
606
+ primary: [
607
+ "bg-accent text-accent-on hover:bg-accent-hover",
608
+ "light:bg-brand-hull light:text-accent-on light:hover:bg-text-secondary"
609
+ ],
610
+ conversion: "bg-warm text-warm-on hover:bg-warm-hover",
611
+ secondary: [
612
+ "border-hairline-hover border bg-transparent text-text-primary",
613
+ "hover:border-accent hover:text-accent"
614
+ ],
615
+ tertiary: [
616
+ "bg-transparent font-mono font-normal text-text-secondary",
617
+ "hover:text-accent hover:underline hover:underline-offset-4"
618
+ ]
619
+ },
620
+ size: {
621
+ sm: "h-8 px-control-sm text-label",
622
+ md: "h-10 px-control-md text-ui",
623
+ lg: "h-12 px-control-lg text-lead",
624
+ /** Cuadrado 42×42, sin texto. Lleva `aria-label` obligatorio. */
625
+ icon: "size-control-icon p-0"
626
+ }
627
+ },
628
+ compoundVariants: [
629
+ /**
630
+ * El terciario no tiene caja: ni padding horizontal ni alto de control.
631
+ * Va aquí y no como `px-0` en la variante para que gane al `px-*` del
632
+ * tamaño sin depender del orden en que cva concatena las clases.
633
+ */
634
+ { variant: "tertiary", size: ["sm", "md", "lg"], class: "h-auto px-0" }
635
+ ],
636
+ defaultVariants: { variant: "primary", size: "md" }
637
+ }
638
+ );
639
+ function Button({
640
+ className,
641
+ variant,
642
+ size: size2,
643
+ asChild = false,
644
+ loading = false,
645
+ icon,
646
+ children,
647
+ disabled,
648
+ ...props
649
+ }) {
650
+ if (asChild) {
651
+ return /* @__PURE__ */ jsxRuntime.jsx(reactSlot.Slot, { className: cn(button({ variant, size: size2 }), className), ...props, children });
652
+ }
653
+ return /* @__PURE__ */ jsxRuntime.jsxs(
654
+ "button",
655
+ {
656
+ className: cn(button({ variant, size: size2 }), className),
657
+ disabled: disabled === true || loading,
658
+ "aria-busy": loading || void 0,
659
+ ...props,
660
+ children: [
661
+ loading ? /* @__PURE__ */ jsxRuntime.jsx(Spinner, {}) : icon,
662
+ children
663
+ ]
664
+ }
665
+ );
666
+ }
667
+ function Calendar({
668
+ className,
669
+ classNames,
670
+ showOutsideDays = true,
671
+ fullWidth = false,
672
+ ...props
673
+ }) {
674
+ const dia = [
675
+ "relative p-0 text-center",
676
+ fullWidth ? "h-9 flex-1" : "size-9",
677
+ "text-ui font-sans text-text-primary"
678
+ ].join(" ");
679
+ const botonDia = [
680
+ fullWidth ? "h-9 w-full" : "size-9",
681
+ "rounded-chip inline-flex items-center justify-center",
682
+ "transition-standard cursor-pointer",
683
+ "hover:bg-surface-raised",
684
+ "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent",
685
+ "disabled:pointer-events-none disabled:opacity-50"
686
+ ].join(" ");
687
+ const navegacion = [
688
+ "size-8 rounded-chip inline-flex items-center justify-center",
689
+ "text-text-secondary transition-standard cursor-pointer",
690
+ "hover:bg-surface-raised hover:text-text-primary",
691
+ "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent",
692
+ "disabled:pointer-events-none disabled:opacity-50"
693
+ ].join(" ");
694
+ return /* @__PURE__ */ jsxRuntime.jsx(
695
+ reactDayPicker.DayPicker,
696
+ {
697
+ locale: locale.es,
698
+ showOutsideDays,
699
+ className: cn("font-sans", className),
700
+ classNames: {
701
+ // `relative` obligatorio: la navegación se posiciona en absoluto contra
702
+ // la raíz, y sin esto se ancla al primer ancestro posicionado —o al
703
+ // viewport— y las flechas acaban en los bordes de la página.
704
+ root: cn("relative", fullWidth ? "w-full" : "w-fit"),
705
+ months: cn("gap-md flex flex-col sm:flex-row", fullWidth && "w-full"),
706
+ month: cn("gap-sm flex flex-col", fullWidth && "min-w-0 flex-1"),
707
+ month_caption: "h-8 flex items-center justify-center",
708
+ caption_label: "text-ui font-sans font-medium text-text-primary capitalize",
709
+ nav: "absolute inset-x-0 top-0 flex items-center justify-between",
710
+ button_previous: navegacion,
711
+ button_next: navegacion,
712
+ month_grid: "w-full border-collapse",
713
+ weekdays: cn("flex", fullWidth && "w-full"),
714
+ // `textMuted` no va sobre `surfaceRaised` —4.07:1—, y un calendario dentro de
715
+ // un Popover vive justo ahí.
716
+ weekday: cn(
717
+ "h-9 text-eyebrow font-mono text-text-secondary uppercase flex items-center justify-center",
718
+ fullWidth ? "flex-1" : "w-9"
719
+ ),
720
+ week: "flex w-full",
721
+ day: dia,
722
+ day_button: botonDia,
723
+ today: "text-accent font-medium",
724
+ // Los días de los meses vecinos se atenúan, pero no por debajo de AA:
725
+ // `textSecondary` al 85 % da 5.09:1 en el peor caso, que es sobre
726
+ // `surfaceRaised`. Al 75 % ya no pasa en modo claro.
727
+ outside: "text-text-secondary opacity-85",
728
+ disabled: "opacity-50",
729
+ hidden: "invisible",
730
+ selected: "[&_button]:bg-accent [&_button]:text-accent-on [&_button]:hover:bg-accent-hover",
731
+ range_start: "[&_button]:bg-accent [&_button]:text-accent-on [&_button]:rounded-r-none",
732
+ range_middle: "[&_button]:bg-surface-raised [&_button]:text-text-primary [&_button]:rounded-none",
733
+ range_end: "[&_button]:bg-accent [&_button]:text-accent-on [&_button]:rounded-l-none",
734
+ footer: "text-label font-sans text-text-secondary pt-sm",
735
+ ...classNames
736
+ },
737
+ components: {
738
+ Chevron: ({ orientation, ...rest }) => orientation === "left" ? /* @__PURE__ */ jsxRuntime.jsx(ChevronLeft, { ...rest }) : /* @__PURE__ */ jsxRuntime.jsx(ChevronRight, { ...rest })
739
+ },
740
+ ...props
741
+ }
742
+ );
743
+ }
744
+ var ETIQUETA = {
745
+ display: "h1",
746
+ stat: "p",
747
+ h1: "h1",
748
+ h2: "h2",
749
+ h3: "h3",
750
+ body: "p",
751
+ lead: "p",
752
+ ui: "p",
753
+ label: "span",
754
+ tag: "span",
755
+ meta: "p",
756
+ chip: "span",
757
+ eyebrow: "p"
758
+ };
759
+ var texto = classVarianceAuthority.cva("", {
760
+ variants: {
761
+ variant: {
762
+ display: "text-display font-display",
763
+ // Métricas grandes: 46px de display. Es la única escala pensada para un
764
+ // número, y por eso el interlineado es 1.
765
+ stat: "text-stat font-display",
766
+ h1: "text-h1 font-display",
767
+ h2: "text-h2 font-display",
768
+ h3: "text-h3 font-display",
769
+ body: "text-body font-sans",
770
+ // 17px: la bajada de las páginas internas y el botón grande.
771
+ lead: "text-lead font-sans",
772
+ ui: "text-ui font-sans",
773
+ label: "text-label font-sans",
774
+ // Las dos escalas de etiqueta. `tag` es el estado (sans 12.5/500) y `chip`
775
+ // la categoría y la métrica (mono 11.5). Ninguna transforma el texto.
776
+ tag: "text-tag font-sans",
777
+ chip: "text-chip font-mono",
778
+ // Mono SIN transformar: fechas, rutas, versiones, nombres de archivo y la
779
+ // firma del footer. Es el escalón que faltaba, y por el que cada sitio de
780
+ // uso terminaba escribiendo `variant="eyebrow" className="normal-case"`.
781
+ meta: "text-meta font-mono",
782
+ // `uppercase` no cabe en un token de tamaño: text-transform no es un
783
+ // modificador de --text-*. Por eso lo pone la variante y no theme.css.
784
+ eyebrow: "text-eyebrow font-mono uppercase"
785
+ },
786
+ tone: {
787
+ primary: "text-text-primary",
788
+ secondary: "text-text-secondary",
789
+ muted: "text-text-muted",
790
+ accent: "text-accent",
791
+ warm: "text-warm",
792
+ success: "text-success",
793
+ warning: "text-warning",
794
+ error: "text-error"
795
+ }
796
+ },
797
+ defaultVariants: { variant: "body", tone: "primary" }
798
+ });
799
+ function Text({
800
+ className,
801
+ variant,
802
+ tone,
803
+ as,
804
+ asChild = false,
805
+ measure,
806
+ children,
807
+ ...props
808
+ }) {
809
+ const escala = variant ?? "body";
810
+ const limitar = measure ?? escala === "body";
811
+ const clases = cn(texto({ variant, tone }), limitar && "max-w-measure", className);
812
+ if (asChild) {
813
+ return /* @__PURE__ */ jsxRuntime.jsx(reactSlot.Slot, { className: clases, ...props, children });
814
+ }
815
+ const Etiqueta = as ?? ETIQUETA[escala];
816
+ return /* @__PURE__ */ jsxRuntime.jsx(Etiqueta, { className: clases, ...props, children });
817
+ }
818
+ var SUPERFICIE_TARJETA = "rounded-card border-hairline bg-surface border";
819
+ var HOVER_TARJETA = "transition-standard hover:border-hairline-hover";
820
+ function Card({ className, ...props }) {
821
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(SUPERFICIE_TARJETA, className), ...props });
822
+ }
823
+ function CardHeader({ className, ...props }) {
824
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("gap-xs p-lg flex flex-col", className), ...props });
825
+ }
826
+ function CardTitle({ className, ...props }) {
827
+ return /* @__PURE__ */ jsxRuntime.jsx(Text, { as: "h3", variant: "h3", className, ...props });
828
+ }
829
+ function CardDescription({ className, ...props }) {
830
+ return /* @__PURE__ */ jsxRuntime.jsx(Text, { variant: "ui", tone: "secondary", className, ...props });
831
+ }
832
+ function CardContent({ className, ...props }) {
833
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("px-lg pb-lg", className), ...props });
834
+ }
835
+ function CardFooter({ className, ...props }) {
836
+ return /* @__PURE__ */ jsxRuntime.jsx(
837
+ "div",
838
+ {
839
+ className: cn("border-hairline px-lg py-md gap-sm flex items-center border-t", className),
840
+ ...props
841
+ }
842
+ );
843
+ }
844
+ function Checkbox({ className, ...props }) {
845
+ return /* @__PURE__ */ jsxRuntime.jsx(
846
+ CheckboxPrimitive__namespace.Root,
847
+ {
848
+ className: cn(
849
+ "rounded-chip border-border bg-surface size-5 shrink-0 cursor-pointer border",
850
+ "text-accent-on transition-standard",
851
+ "hover:border-hairline-hover",
852
+ "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent",
853
+ "disabled:pointer-events-none disabled:opacity-50",
854
+ "data-[state=checked]:border-accent data-[state=checked]:bg-accent",
855
+ "data-[state=indeterminate]:border-accent data-[state=indeterminate]:bg-accent",
856
+ className
857
+ ),
858
+ ...props,
859
+ children: /* @__PURE__ */ jsxRuntime.jsx(CheckboxPrimitive__namespace.Indicator, { className: "flex items-center justify-center text-[13px]", children: props.checked === "indeterminate" ? /* @__PURE__ */ jsxRuntime.jsx(Minus, {}) : /* @__PURE__ */ jsxRuntime.jsx(Check, {}) })
860
+ }
861
+ );
862
+ }
863
+ function Code({ className, ...props }) {
864
+ return /* @__PURE__ */ jsxRuntime.jsx(
865
+ "code",
866
+ {
867
+ className: cn(
868
+ "rounded-chip border-hairline bg-surface-raised border",
869
+ "font-mono text-meta text-text-primary",
870
+ "px-1 py-0.5",
871
+ className
872
+ ),
873
+ ...props
874
+ }
875
+ );
876
+ }
877
+ function DateField({
878
+ className,
879
+ invalid = false,
880
+ withTime = false,
881
+ ...props
882
+ }) {
883
+ return /* @__PURE__ */ jsxRuntime.jsx(
884
+ "input",
885
+ {
886
+ type: withTime ? "datetime-local" : "date",
887
+ "data-invalid": invalid || void 0,
888
+ "aria-invalid": invalid || void 0,
889
+ className: cn(
890
+ "px-sm h-10 w-full",
891
+ "rounded-control border-border bg-surface border",
892
+ "font-mono text-ui text-text-primary",
893
+ "transition-standard",
894
+ "hover:border-hairline-hover",
895
+ "focus-visible:border-accent focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent",
896
+ "disabled:pointer-events-none disabled:opacity-50",
897
+ "data-[invalid]:border-error data-[invalid]:focus-visible:outline-error",
898
+ // El indicador nativo hereda el esquema del tema activo.
899
+ "scheme-light dark:scheme-dark [&::-webkit-calendar-picker-indicator]:cursor-pointer",
900
+ className
901
+ ),
902
+ ...props
903
+ }
904
+ );
905
+ }
906
+ var Dialog = DialogPrimitive__namespace.Root;
907
+ var DialogTrigger = DialogPrimitive__namespace.Trigger;
908
+ var DialogClose = DialogPrimitive__namespace.Close;
909
+ function DialogOverlay({
910
+ className,
911
+ ...props
912
+ }) {
913
+ return /* @__PURE__ */ jsxRuntime.jsx(
914
+ DialogPrimitive__namespace.Overlay,
915
+ {
916
+ className: cn("bg-brand-hull/70 fixed inset-0 z-50", className),
917
+ ...props
918
+ }
919
+ );
920
+ }
921
+ function DialogContent({
922
+ className,
923
+ children,
924
+ ...props
925
+ }) {
926
+ return /* @__PURE__ */ jsxRuntime.jsxs(DialogPrimitive__namespace.Portal, { children: [
927
+ /* @__PURE__ */ jsxRuntime.jsx(DialogOverlay, {}),
928
+ /* @__PURE__ */ jsxRuntime.jsxs(
929
+ DialogPrimitive__namespace.Content,
930
+ {
931
+ className: cn(
932
+ "fixed top-1/2 left-1/2 z-50 w-full max-w-content -translate-x-1/2 -translate-y-1/2",
933
+ "gap-md p-lg flex flex-col",
934
+ "rounded-panel border-border bg-surface shadow-standard border",
935
+ "text-text-primary font-sans",
936
+ className
937
+ ),
938
+ ...props,
939
+ children: [
940
+ children,
941
+ /* @__PURE__ */ jsxRuntime.jsx(
942
+ DialogPrimitive__namespace.Close,
943
+ {
944
+ "aria-label": "Cerrar",
945
+ className: cn(
946
+ "rounded-chip text-text-muted absolute top-4 right-4 flex size-8 cursor-pointer items-center justify-center",
947
+ "transition-standard",
948
+ "hover:bg-surface-raised hover:text-text-primary",
949
+ "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent"
950
+ ),
951
+ children: /* @__PURE__ */ jsxRuntime.jsx(Close, {})
952
+ }
953
+ )
954
+ ]
955
+ }
956
+ )
957
+ ] });
958
+ }
959
+ function DialogHeader({ className, ...props }) {
960
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("gap-xs flex flex-col pr-8", className), ...props });
961
+ }
962
+ function DialogFooter({ className, ...props }) {
963
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("gap-sm flex flex-col-reverse sm:flex-row sm:justify-end", className), ...props });
964
+ }
965
+ function DialogTitle({
966
+ className,
967
+ ...props
968
+ }) {
969
+ return /* @__PURE__ */ jsxRuntime.jsx(
970
+ DialogPrimitive__namespace.Title,
971
+ {
972
+ className: cn("text-h3 font-display text-text-primary", className),
973
+ ...props
974
+ }
975
+ );
976
+ }
977
+ function DialogDescription({
978
+ className,
979
+ ...props
980
+ }) {
981
+ return /* @__PURE__ */ jsxRuntime.jsx(
982
+ DialogPrimitive__namespace.Description,
983
+ {
984
+ className: cn("text-ui text-text-secondary max-w-measure", className),
985
+ ...props
986
+ }
987
+ );
988
+ }
989
+ var DropdownMenu = DropdownMenuPrimitive__namespace.Root;
990
+ var DropdownMenuTrigger = DropdownMenuPrimitive__namespace.Trigger;
991
+ var DropdownMenuGroup = DropdownMenuPrimitive__namespace.Group;
992
+ var DropdownMenuRadioGroup = DropdownMenuPrimitive__namespace.RadioGroup;
993
+ var DropdownMenuSub = DropdownMenuPrimitive__namespace.Sub;
994
+ var panel = [
995
+ "z-50 min-w-40 overflow-hidden p-1",
996
+ "rounded-panel border-border bg-surface-raised shadow-standard border",
997
+ "text-text-primary font-sans"
998
+ ];
999
+ var item = [
1000
+ "rounded-chip px-sm relative flex h-9 cursor-default items-center gap-2 select-none",
1001
+ "text-ui text-text-secondary transition-standard",
1002
+ "data-[highlighted]:bg-surface data-[highlighted]:text-text-primary",
1003
+ "data-[disabled]:pointer-events-none data-[disabled]:opacity-50"
1004
+ ];
1005
+ function DropdownMenuContent({
1006
+ className,
1007
+ sideOffset = 6,
1008
+ ...props
1009
+ }) {
1010
+ return /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
1011
+ DropdownMenuPrimitive__namespace.Content,
1012
+ {
1013
+ sideOffset,
1014
+ className: cn(panel, className),
1015
+ ...props
1016
+ }
1017
+ ) });
1018
+ }
1019
+ function DropdownMenuItem({
1020
+ className,
1021
+ ...props
1022
+ }) {
1023
+ return /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuPrimitive__namespace.Item, { className: cn(item, className), ...props });
1024
+ }
1025
+ function DropdownMenuCheckboxItem({
1026
+ className,
1027
+ children,
1028
+ ...props
1029
+ }) {
1030
+ return /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuPrimitive__namespace.CheckboxItem, { className: cn(item, "pl-8", className), ...props, children: [
1031
+ /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuPrimitive__namespace.ItemIndicator, { className: "text-accent absolute left-2 flex items-center", children: /* @__PURE__ */ jsxRuntime.jsx(Check, {}) }),
1032
+ children
1033
+ ] });
1034
+ }
1035
+ function DropdownMenuRadioItem({
1036
+ className,
1037
+ children,
1038
+ ...props
1039
+ }) {
1040
+ return /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuPrimitive__namespace.RadioItem, { className: cn(item, "pl-8", className), ...props, children: [
1041
+ /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuPrimitive__namespace.ItemIndicator, { className: "absolute left-2 flex items-center", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "rounded-pill bg-accent block size-2" }) }),
1042
+ children
1043
+ ] });
1044
+ }
1045
+ function DropdownMenuLabel({
1046
+ className,
1047
+ ...props
1048
+ }) {
1049
+ return /* @__PURE__ */ jsxRuntime.jsx(
1050
+ DropdownMenuPrimitive__namespace.Label,
1051
+ {
1052
+ className: cn("px-sm text-eyebrow font-mono text-text-secondary py-1.5 uppercase", className),
1053
+ ...props
1054
+ }
1055
+ );
1056
+ }
1057
+ function DropdownMenuSeparator({
1058
+ className,
1059
+ ...props
1060
+ }) {
1061
+ return /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuPrimitive__namespace.Separator, { className: cn("bg-hairline my-1 h-px", className), ...props });
1062
+ }
1063
+ function DropdownMenuSubTrigger({
1064
+ className,
1065
+ children,
1066
+ ...props
1067
+ }) {
1068
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1069
+ DropdownMenuPrimitive__namespace.SubTrigger,
1070
+ {
1071
+ className: cn(item, "data-[state=open]:bg-surface", className),
1072
+ ...props,
1073
+ children: [
1074
+ children,
1075
+ /* @__PURE__ */ jsxRuntime.jsx(ChevronRight, { className: "text-text-muted ml-auto" })
1076
+ ]
1077
+ }
1078
+ );
1079
+ }
1080
+ function DropdownMenuSubContent({
1081
+ className,
1082
+ ...props
1083
+ }) {
1084
+ return /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuPrimitive__namespace.SubContent, { className: cn(panel, className), ...props }) });
1085
+ }
1086
+ function Input({ className, invalid = false, ...props }) {
1087
+ return /* @__PURE__ */ jsxRuntime.jsx(
1088
+ "input",
1089
+ {
1090
+ "data-invalid": invalid || void 0,
1091
+ "aria-invalid": invalid || void 0,
1092
+ className: cn(
1093
+ "h-10 w-full px-sm",
1094
+ "rounded-control border border-border bg-surface",
1095
+ "font-sans text-ui text-text-primary placeholder:text-text-muted",
1096
+ "transition-standard",
1097
+ "hover:border-hairline-hover",
1098
+ "focus-visible:border-accent focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent",
1099
+ "disabled:pointer-events-none disabled:opacity-50",
1100
+ "data-[invalid]:border-error data-[invalid]:focus-visible:outline-error",
1101
+ "file:mr-sm file:border-0 file:bg-transparent file:font-sans file:text-label file:text-text-secondary",
1102
+ className
1103
+ ),
1104
+ ...props
1105
+ }
1106
+ );
1107
+ }
1108
+ function Label2({ className, ...props }) {
1109
+ return /* @__PURE__ */ jsxRuntime.jsx(
1110
+ LabelPrimitive__namespace.Root,
1111
+ {
1112
+ className: cn(
1113
+ "text-label font-sans text-text-secondary select-none",
1114
+ "peer-disabled:opacity-50 group-data-[disabled]:opacity-50",
1115
+ className
1116
+ ),
1117
+ ...props
1118
+ }
1119
+ );
1120
+ }
1121
+ function Pagination({ className, ...props }) {
1122
+ return /* @__PURE__ */ jsxRuntime.jsx(
1123
+ "nav",
1124
+ {
1125
+ role: "navigation",
1126
+ "aria-label": "Paginaci\xF3n",
1127
+ className: cn("mx-auto flex w-full justify-center", className),
1128
+ ...props
1129
+ }
1130
+ );
1131
+ }
1132
+ function PaginationContent({ className, ...props }) {
1133
+ return /* @__PURE__ */ jsxRuntime.jsx("ul", { className: cn("gap-xs flex flex-row items-center", className), ...props });
1134
+ }
1135
+ function PaginationItem(props) {
1136
+ return /* @__PURE__ */ jsxRuntime.jsx("li", { ...props });
1137
+ }
1138
+ function PaginationLink({ className, isActive = false, ...props }) {
1139
+ return /* @__PURE__ */ jsxRuntime.jsx(
1140
+ "a",
1141
+ {
1142
+ "aria-current": isActive ? "page" : void 0,
1143
+ className: cn(
1144
+ "rounded-chip px-sm inline-flex h-9 min-w-9 cursor-pointer items-center justify-center",
1145
+ "font-sans text-ui text-text-secondary",
1146
+ "transition-standard",
1147
+ "hover:bg-surface hover:text-text-primary",
1148
+ "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent",
1149
+ isActive && "bg-surface-raised text-text-primary",
1150
+ className
1151
+ ),
1152
+ ...props
1153
+ }
1154
+ );
1155
+ }
1156
+ function PaginationPrevious({ className, ...props }) {
1157
+ return /* @__PURE__ */ jsxRuntime.jsxs(PaginationLink, { "aria-label": "P\xE1gina anterior", className: cn("gap-xs", className), ...props, children: [
1158
+ /* @__PURE__ */ jsxRuntime.jsx(ChevronLeft, {}),
1159
+ "Anterior"
1160
+ ] });
1161
+ }
1162
+ function PaginationNext({ className, ...props }) {
1163
+ return /* @__PURE__ */ jsxRuntime.jsxs(PaginationLink, { "aria-label": "P\xE1gina siguiente", className: cn("gap-xs", className), ...props, children: [
1164
+ "Siguiente",
1165
+ /* @__PURE__ */ jsxRuntime.jsx(ChevronRight, {})
1166
+ ] });
1167
+ }
1168
+ function PaginationEllipsis({ className, ...props }) {
1169
+ return /* @__PURE__ */ jsxRuntime.jsx(
1170
+ "span",
1171
+ {
1172
+ "aria-hidden": "true",
1173
+ className: cn("text-text-muted flex size-9 items-center justify-center", className),
1174
+ ...props,
1175
+ children: /* @__PURE__ */ jsxRuntime.jsx(Ellipsis, {})
1176
+ }
1177
+ );
1178
+ }
1179
+ var Popover = PopoverPrimitive__namespace.Root;
1180
+ var PopoverTrigger = PopoverPrimitive__namespace.Trigger;
1181
+ var PopoverAnchor = PopoverPrimitive__namespace.Anchor;
1182
+ function PopoverContent({
1183
+ className,
1184
+ align = "center",
1185
+ sideOffset = 6,
1186
+ ...props
1187
+ }) {
1188
+ return /* @__PURE__ */ jsxRuntime.jsx(PopoverPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
1189
+ PopoverPrimitive__namespace.Content,
1190
+ {
1191
+ align,
1192
+ sideOffset,
1193
+ className: cn(
1194
+ "z-50 w-72 p-md",
1195
+ "rounded-panel border-border bg-surface-raised shadow-standard border",
1196
+ "text-text-primary font-sans text-ui",
1197
+ "outline-none",
1198
+ className
1199
+ ),
1200
+ ...props
1201
+ }
1202
+ ) });
1203
+ }
1204
+ function Progress({ className, value, label, tone = "accent", ...props }) {
1205
+ return /* @__PURE__ */ jsxRuntime.jsx(
1206
+ ProgressPrimitive__namespace.Root,
1207
+ {
1208
+ className: cn("rounded-pill bg-surface-raised relative h-2 w-full overflow-hidden", className),
1209
+ value,
1210
+ "aria-label": label,
1211
+ ...props,
1212
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1213
+ ProgressPrimitive__namespace.Indicator,
1214
+ {
1215
+ className: cn("h-full", tone === "warm" ? "bg-warm" : "bg-accent"),
1216
+ style: { width: `${value ?? 0}%` }
1217
+ }
1218
+ )
1219
+ }
1220
+ );
1221
+ }
1222
+ function RadioGroup2({ className, ...props }) {
1223
+ return /* @__PURE__ */ jsxRuntime.jsx(RadioGroupPrimitive__namespace.Root, { className: cn("gap-sm grid", className), ...props });
1224
+ }
1225
+ function RadioGroupItem({ className, ...props }) {
1226
+ return /* @__PURE__ */ jsxRuntime.jsx(
1227
+ RadioGroupPrimitive__namespace.Item,
1228
+ {
1229
+ className: cn(
1230
+ "rounded-pill border-border bg-surface size-5 shrink-0 cursor-pointer border",
1231
+ "transition-standard",
1232
+ "hover:border-hairline-hover",
1233
+ "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent",
1234
+ "disabled:pointer-events-none disabled:opacity-50",
1235
+ "data-[state=checked]:border-accent",
1236
+ className
1237
+ ),
1238
+ ...props,
1239
+ children: /* @__PURE__ */ jsxRuntime.jsx(RadioGroupPrimitive__namespace.Indicator, { className: "flex size-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "rounded-pill bg-accent block size-2.5" }) })
1240
+ }
1241
+ );
1242
+ }
1243
+ var Select = SelectPrimitive__namespace.Root;
1244
+ var SelectGroup = SelectPrimitive__namespace.Group;
1245
+ var SelectValue = SelectPrimitive__namespace.Value;
1246
+ function SelectTrigger({
1247
+ className,
1248
+ children,
1249
+ ...props
1250
+ }) {
1251
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1252
+ SelectPrimitive__namespace.Trigger,
1253
+ {
1254
+ className: cn(
1255
+ "gap-sm px-sm flex h-10 w-full cursor-pointer items-center justify-between",
1256
+ "rounded-control border-border bg-surface border",
1257
+ "font-sans text-ui text-text-primary",
1258
+ "transition-standard",
1259
+ "hover:border-hairline-hover",
1260
+ "focus-visible:border-accent focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent",
1261
+ "disabled:pointer-events-none disabled:opacity-50",
1262
+ "data-[placeholder]:text-text-muted",
1263
+ className
1264
+ ),
1265
+ ...props,
1266
+ children: [
1267
+ children,
1268
+ /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.Icon, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ChevronDown, { className: "text-text-muted" }) })
1269
+ ]
1270
+ }
1271
+ );
1272
+ }
1273
+ function SelectContent({
1274
+ className,
1275
+ children,
1276
+ position = "popper",
1277
+ ...props
1278
+ }) {
1279
+ return /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs(
1280
+ SelectPrimitive__namespace.Content,
1281
+ {
1282
+ position,
1283
+ className: cn(
1284
+ "relative z-50 max-h-96 min-w-32 overflow-hidden",
1285
+ "rounded-panel border-border bg-surface-raised shadow-standard border",
1286
+ "text-text-primary font-sans",
1287
+ position === "popper" && "w-full min-w-[var(--radix-select-trigger-width)]",
1288
+ className
1289
+ ),
1290
+ ...props,
1291
+ children: [
1292
+ /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.ScrollUpButton, { className: "text-text-secondary flex h-6 items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ChevronUp, {}) }),
1293
+ /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.Viewport, { className: "p-1", children }),
1294
+ /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.ScrollDownButton, { className: "text-text-secondary flex h-6 items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ChevronDown, {}) })
1295
+ ]
1296
+ }
1297
+ ) });
1298
+ }
1299
+ function SelectLabel({
1300
+ className,
1301
+ ...props
1302
+ }) {
1303
+ return /* @__PURE__ */ jsxRuntime.jsx(
1304
+ SelectPrimitive__namespace.Label,
1305
+ {
1306
+ className: cn("px-sm text-eyebrow font-mono text-text-secondary py-1.5 uppercase", className),
1307
+ ...props
1308
+ }
1309
+ );
1310
+ }
1311
+ function SelectItem({
1312
+ className,
1313
+ children,
1314
+ ...props
1315
+ }) {
1316
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1317
+ SelectPrimitive__namespace.Item,
1318
+ {
1319
+ className: cn(
1320
+ "rounded-chip px-sm relative flex h-9 w-full cursor-default items-center pr-8 select-none",
1321
+ "text-ui text-text-secondary transition-standard",
1322
+ "data-[highlighted]:bg-surface data-[highlighted]:text-text-primary",
1323
+ "data-[state=checked]:text-text-primary",
1324
+ "data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
1325
+ className
1326
+ ),
1327
+ ...props,
1328
+ children: [
1329
+ /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.ItemText, { children }),
1330
+ /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.ItemIndicator, { className: "text-accent absolute right-2 flex items-center", children: /* @__PURE__ */ jsxRuntime.jsx(Check, {}) })
1331
+ ]
1332
+ }
1333
+ );
1334
+ }
1335
+ function SelectSeparator({
1336
+ className,
1337
+ ...props
1338
+ }) {
1339
+ return /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.Separator, { className: cn("bg-hairline my-1 h-px", className), ...props });
1340
+ }
1341
+ function Separator3({
1342
+ className,
1343
+ orientation = "horizontal",
1344
+ decorative = true,
1345
+ ...props
1346
+ }) {
1347
+ return /* @__PURE__ */ jsxRuntime.jsx(
1348
+ SeparatorPrimitive__namespace.Root,
1349
+ {
1350
+ orientation,
1351
+ decorative,
1352
+ className: cn(
1353
+ "bg-hairline shrink-0",
1354
+ orientation === "horizontal" ? "h-px w-full" : "h-full w-px",
1355
+ className
1356
+ ),
1357
+ ...props
1358
+ }
1359
+ );
1360
+ }
1361
+ var Sheet = DialogPrimitive__namespace.Root;
1362
+ var SheetTrigger = DialogPrimitive__namespace.Trigger;
1363
+ var SheetClose = DialogPrimitive__namespace.Close;
1364
+ var panel2 = classVarianceAuthority.cva(
1365
+ [
1366
+ "bg-surface border-border shadow-standard fixed z-50 flex flex-col",
1367
+ "text-text-primary font-sans outline-none"
1368
+ ],
1369
+ {
1370
+ variants: {
1371
+ side: {
1372
+ right: [
1373
+ "inset-y-0 right-0 h-full w-3/4 max-w-content border-l",
1374
+ "motion-safe:data-[state=open]:deslizar-entra-derecha",
1375
+ "motion-safe:data-[state=closed]:deslizar-sale-derecha"
1376
+ ],
1377
+ left: [
1378
+ "inset-y-0 left-0 h-full w-3/4 max-w-content border-r",
1379
+ "motion-safe:data-[state=open]:deslizar-entra-izquierda",
1380
+ "motion-safe:data-[state=closed]:deslizar-sale-izquierda"
1381
+ ],
1382
+ top: [
1383
+ "inset-x-0 top-0 border-b",
1384
+ "motion-safe:data-[state=open]:deslizar-entra-arriba",
1385
+ "motion-safe:data-[state=closed]:deslizar-sale-arriba"
1386
+ ],
1387
+ bottom: [
1388
+ "inset-x-0 bottom-0 border-t",
1389
+ "motion-safe:data-[state=open]:deslizar-entra-abajo",
1390
+ "motion-safe:data-[state=closed]:deslizar-sale-abajo"
1391
+ ]
1392
+ }
1393
+ },
1394
+ defaultVariants: { side: "right" }
1395
+ }
1396
+ );
1397
+ function SheetContent({ className, side, children, ...props }) {
1398
+ return /* @__PURE__ */ jsxRuntime.jsxs(DialogPrimitive__namespace.Portal, { children: [
1399
+ /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Overlay, { className: "bg-brand-hull/70 fixed inset-0 z-50" }),
1400
+ /* @__PURE__ */ jsxRuntime.jsxs(DialogPrimitive__namespace.Content, { className: cn(panel2({ side }), className), ...props, children: [
1401
+ children,
1402
+ /* @__PURE__ */ jsxRuntime.jsx(
1403
+ DialogPrimitive__namespace.Close,
1404
+ {
1405
+ "aria-label": "Cerrar",
1406
+ className: cn(
1407
+ "rounded-chip text-text-muted absolute top-4 right-4 flex size-8 cursor-pointer items-center justify-center",
1408
+ "transition-standard",
1409
+ "hover:bg-surface-raised hover:text-text-primary",
1410
+ "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent"
1411
+ ),
1412
+ children: /* @__PURE__ */ jsxRuntime.jsx(Close, {})
1413
+ }
1414
+ )
1415
+ ] })
1416
+ ] });
1417
+ }
1418
+ function SheetHeader({ className, ...props }) {
1419
+ return /* @__PURE__ */ jsxRuntime.jsx(
1420
+ "div",
1421
+ {
1422
+ className: cn("border-hairline gap-xs p-lg flex flex-col border-b pr-12", className),
1423
+ ...props
1424
+ }
1425
+ );
1426
+ }
1427
+ function SheetBody({ className, ...props }) {
1428
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("p-lg flex-1 overflow-y-auto", className), ...props });
1429
+ }
1430
+ function SheetFooter({ className, ...props }) {
1431
+ return /* @__PURE__ */ jsxRuntime.jsx(
1432
+ "div",
1433
+ {
1434
+ className: cn("border-hairline gap-sm p-lg flex flex-wrap justify-end border-t", className),
1435
+ ...props
1436
+ }
1437
+ );
1438
+ }
1439
+ function SheetTitle({
1440
+ className,
1441
+ ...props
1442
+ }) {
1443
+ return /* @__PURE__ */ jsxRuntime.jsx(
1444
+ DialogPrimitive__namespace.Title,
1445
+ {
1446
+ className: cn("text-h3 font-display text-text-primary", className),
1447
+ ...props
1448
+ }
1449
+ );
1450
+ }
1451
+ function SheetDescription({
1452
+ className,
1453
+ ...props
1454
+ }) {
1455
+ return /* @__PURE__ */ jsxRuntime.jsx(
1456
+ DialogPrimitive__namespace.Description,
1457
+ {
1458
+ className: cn("text-ui text-text-secondary max-w-measure", className),
1459
+ ...props
1460
+ }
1461
+ );
1462
+ }
1463
+ function Skeleton({ className, still = false, ...props }) {
1464
+ return /* @__PURE__ */ jsxRuntime.jsx(
1465
+ "div",
1466
+ {
1467
+ "aria-hidden": "true",
1468
+ className: cn(
1469
+ "rounded-chip bg-surface-raised",
1470
+ !still && "motion-safe:shimmer",
1471
+ className
1472
+ ),
1473
+ ...props
1474
+ }
1475
+ );
1476
+ }
1477
+ function Switch({ className, ...props }) {
1478
+ return /* @__PURE__ */ jsxRuntime.jsx(
1479
+ SwitchPrimitive__namespace.Root,
1480
+ {
1481
+ className: cn(
1482
+ "rounded-pill border-border bg-surface-raised inline-flex h-6 w-11 shrink-0 cursor-pointer items-center border",
1483
+ "transition-standard",
1484
+ "hover:border-hairline-hover",
1485
+ "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent",
1486
+ "disabled:pointer-events-none disabled:opacity-50",
1487
+ "data-[state=checked]:border-accent data-[state=checked]:bg-accent",
1488
+ className
1489
+ ),
1490
+ ...props,
1491
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1492
+ SwitchPrimitive__namespace.Thumb,
1493
+ {
1494
+ className: cn(
1495
+ "rounded-pill bg-text-secondary pointer-events-none block size-4 translate-x-1",
1496
+ "data-[state=checked]:bg-accent-on data-[state=checked]:translate-x-6"
1497
+ )
1498
+ }
1499
+ )
1500
+ }
1501
+ );
1502
+ }
1503
+ function Table({ className, ...props }) {
1504
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsx(
1505
+ "table",
1506
+ {
1507
+ className: cn("w-full caption-bottom border-collapse font-sans text-ui", className),
1508
+ ...props
1509
+ }
1510
+ ) });
1511
+ }
1512
+ function TableHeader({ className, ...props }) {
1513
+ return /* @__PURE__ */ jsxRuntime.jsx("thead", { className: cn("[&_tr]:border-hairline [&_tr]:border-b", className), ...props });
1514
+ }
1515
+ function TableBody({ className, ...props }) {
1516
+ return /* @__PURE__ */ jsxRuntime.jsx("tbody", { className, ...props });
1517
+ }
1518
+ function TableFooter({ className, ...props }) {
1519
+ return /* @__PURE__ */ jsxRuntime.jsx(
1520
+ "tfoot",
1521
+ {
1522
+ className: cn("border-hairline bg-surface text-text-secondary border-t", className),
1523
+ ...props
1524
+ }
1525
+ );
1526
+ }
1527
+ function TableRow({ className, ...props }) {
1528
+ return /* @__PURE__ */ jsxRuntime.jsx(
1529
+ "tr",
1530
+ {
1531
+ className: cn(
1532
+ "border-hairline transition-standard border-b last:border-b-0",
1533
+ "hover:bg-surface data-[state=selected]:bg-surface-raised",
1534
+ className
1535
+ ),
1536
+ ...props
1537
+ }
1538
+ );
1539
+ }
1540
+ function TableHead({ className, ...props }) {
1541
+ return /* @__PURE__ */ jsxRuntime.jsx(
1542
+ "th",
1543
+ {
1544
+ className: cn(
1545
+ "px-sm h-10 text-left align-middle",
1546
+ "text-eyebrow font-mono text-text-muted uppercase",
1547
+ className
1548
+ ),
1549
+ ...props
1550
+ }
1551
+ );
1552
+ }
1553
+ function TableCell({ className, ...props }) {
1554
+ return /* @__PURE__ */ jsxRuntime.jsx("td", { className: cn("px-sm py-sm text-text-secondary align-middle", className), ...props });
1555
+ }
1556
+ function TableCaption({ className, ...props }) {
1557
+ return /* @__PURE__ */ jsxRuntime.jsx("caption", { className: cn("mt-sm text-label text-text-muted", className), ...props });
1558
+ }
1559
+ function Tabs({ className, ...props }) {
1560
+ return /* @__PURE__ */ jsxRuntime.jsx(TabsPrimitive__namespace.Root, { className: cn("gap-md flex flex-col", className), ...props });
1561
+ }
1562
+ function TabsList({
1563
+ className,
1564
+ ...props
1565
+ }) {
1566
+ return /* @__PURE__ */ jsxRuntime.jsx(
1567
+ TabsPrimitive__namespace.List,
1568
+ {
1569
+ className: cn("rounded-control bg-surface gap-xs inline-flex items-center p-1", className),
1570
+ ...props
1571
+ }
1572
+ );
1573
+ }
1574
+ function TabsTrigger({
1575
+ className,
1576
+ ...props
1577
+ }) {
1578
+ return /* @__PURE__ */ jsxRuntime.jsx(
1579
+ TabsPrimitive__namespace.Trigger,
1580
+ {
1581
+ className: cn(
1582
+ "rounded-chip px-sm inline-flex h-8 cursor-pointer items-center justify-center whitespace-nowrap",
1583
+ "font-sans text-label text-text-secondary",
1584
+ "transition-standard",
1585
+ "hover:text-text-primary",
1586
+ "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent",
1587
+ "disabled:pointer-events-none disabled:opacity-50",
1588
+ "data-[state=active]:bg-surface-raised data-[state=active]:text-text-primary",
1589
+ className
1590
+ ),
1591
+ ...props
1592
+ }
1593
+ );
1594
+ }
1595
+ function TabsContent({
1596
+ className,
1597
+ ...props
1598
+ }) {
1599
+ return /* @__PURE__ */ jsxRuntime.jsx(
1600
+ TabsPrimitive__namespace.Content,
1601
+ {
1602
+ className: cn(
1603
+ "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent",
1604
+ className
1605
+ ),
1606
+ ...props
1607
+ }
1608
+ );
1609
+ }
1610
+ function Textarea({ className, invalid = false, ...props }) {
1611
+ return /* @__PURE__ */ jsxRuntime.jsx(
1612
+ "textarea",
1613
+ {
1614
+ "data-invalid": invalid || void 0,
1615
+ "aria-invalid": invalid || void 0,
1616
+ className: cn(
1617
+ "min-h-24 w-full px-sm py-xs",
1618
+ "rounded-control border border-border bg-surface",
1619
+ "font-sans text-ui text-text-primary placeholder:text-text-muted",
1620
+ "transition-standard",
1621
+ "hover:border-hairline-hover",
1622
+ "focus-visible:border-accent focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent",
1623
+ "disabled:pointer-events-none disabled:opacity-50",
1624
+ "data-[invalid]:border-error data-[invalid]:focus-visible:outline-error",
1625
+ className
1626
+ ),
1627
+ ...props
1628
+ }
1629
+ );
1630
+ }
1631
+ var ToastProvider = ToastPrimitive__namespace.Provider;
1632
+ var ToastAction = ToastPrimitive__namespace.Action;
1633
+ function ToastViewport({
1634
+ className,
1635
+ ...props
1636
+ }) {
1637
+ return /* @__PURE__ */ jsxRuntime.jsx(
1638
+ ToastPrimitive__namespace.Viewport,
1639
+ {
1640
+ className: cn(
1641
+ "gap-sm p-lg fixed right-0 bottom-0 z-50 flex max-h-screen w-full flex-col-reverse",
1642
+ "sm:max-w-[420px] sm:flex-col",
1643
+ className
1644
+ ),
1645
+ ...props
1646
+ }
1647
+ );
1648
+ }
1649
+ var toast = classVarianceAuthority.cva(
1650
+ [
1651
+ "gap-md p-md pr-10 relative flex w-full items-start justify-between",
1652
+ "rounded-card border bg-surface shadow-standard",
1653
+ "font-sans text-ui text-text-secondary"
1654
+ ],
1655
+ {
1656
+ variants: {
1657
+ variant: {
1658
+ neutral: "border-border",
1659
+ success: "border-success/40",
1660
+ error: "border-error/40"
1661
+ }
1662
+ },
1663
+ defaultVariants: { variant: "neutral" }
1664
+ }
1665
+ );
1666
+ function Toast({ className, variant, children, ...props }) {
1667
+ return /* @__PURE__ */ jsxRuntime.jsxs(ToastPrimitive__namespace.Root, { className: cn(toast({ variant }), className), ...props, children: [
1668
+ children,
1669
+ /* @__PURE__ */ jsxRuntime.jsx(
1670
+ ToastPrimitive__namespace.Close,
1671
+ {
1672
+ "aria-label": "Cerrar",
1673
+ className: cn(
1674
+ "rounded-chip text-text-muted absolute top-3 right-3 flex size-7 cursor-pointer items-center justify-center",
1675
+ "transition-standard",
1676
+ "hover:bg-surface-raised hover:text-text-primary",
1677
+ "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent"
1678
+ ),
1679
+ children: /* @__PURE__ */ jsxRuntime.jsx(Close, {})
1680
+ }
1681
+ )
1682
+ ] });
1683
+ }
1684
+ function ToastTitle({
1685
+ className,
1686
+ ...props
1687
+ }) {
1688
+ return /* @__PURE__ */ jsxRuntime.jsx(
1689
+ ToastPrimitive__namespace.Title,
1690
+ {
1691
+ className: cn("text-text-primary mb-1 font-medium", className),
1692
+ ...props
1693
+ }
1694
+ );
1695
+ }
1696
+ function ToastDescription({
1697
+ className,
1698
+ ...props
1699
+ }) {
1700
+ return /* @__PURE__ */ jsxRuntime.jsx(ToastPrimitive__namespace.Description, { className: cn("max-w-measure", className), ...props });
1701
+ }
1702
+ var TooltipProvider = TooltipPrimitive__namespace.Provider;
1703
+ var Tooltip = TooltipPrimitive__namespace.Root;
1704
+ var TooltipTrigger = TooltipPrimitive__namespace.Trigger;
1705
+ function TooltipContent({
1706
+ className,
1707
+ sideOffset = 6,
1708
+ ...props
1709
+ }) {
1710
+ return /* @__PURE__ */ jsxRuntime.jsx(TooltipPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
1711
+ TooltipPrimitive__namespace.Content,
1712
+ {
1713
+ sideOffset,
1714
+ className: cn(
1715
+ "z-50 px-sm py-1.5",
1716
+ "rounded-chip border-border bg-surface-raised shadow-standard border",
1717
+ "font-sans text-label text-text-primary",
1718
+ className
1719
+ ),
1720
+ ...props
1721
+ }
1722
+ ) });
1723
+ }
1724
+ var TARJETA = [
1725
+ "group block cursor-pointer",
1726
+ SUPERFICIE_TARJETA,
1727
+ HOVER_TARJETA,
1728
+ "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent"
1729
+ ];
1730
+ function Tarjeta({ asChild = false, className, children, ...props }) {
1731
+ const Raiz = asChild ? reactSlot.Slot : "a";
1732
+ return /* @__PURE__ */ jsxRuntime.jsx(Raiz, { className: cn(TARJETA, className), ...props, children });
1733
+ }
1734
+ function ArticleCard({
1735
+ title,
1736
+ excerpt,
1737
+ date,
1738
+ dateTime,
1739
+ readingMinutes,
1740
+ tags,
1741
+ className,
1742
+ ...props
1743
+ }) {
1744
+ const meta = [
1745
+ date ? /* @__PURE__ */ jsxRuntime.jsx("time", { dateTime, children: date }, "fecha") : null,
1746
+ readingMinutes ? /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
1747
+ readingMinutes,
1748
+ " min de lectura"
1749
+ ] }, "lectura") : null
1750
+ ].filter(Boolean);
1751
+ return /* @__PURE__ */ jsxRuntime.jsx(Tarjeta, { className: cn("p-lg", className), ...props, children: /* @__PURE__ */ jsxRuntime.jsxs("article", { className: "gap-sm flex h-full flex-col", children: [
1752
+ meta.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(Text, { variant: "meta", tone: "muted", as: "p", className: "gap-xs flex items-center", children: meta.map((m, i) => /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "gap-xs flex items-center", children: [
1753
+ i > 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: "\xB7" }) : null,
1754
+ m
1755
+ ] }, i)) }) : null,
1756
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { as: "h3", variant: "h3", className: "group-hover:text-accent transition-standard", children: title }),
1757
+ excerpt ? /* @__PURE__ */ jsxRuntime.jsx(Text, { variant: "ui", tone: "secondary", className: "line-clamp-2", children: excerpt }) : null,
1758
+ tags && tags.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "gap-xs mt-auto flex flex-wrap pt-sm", children: tags.map((t) => /* @__PURE__ */ jsxRuntime.jsx(CategoryBadge, { children: t }, t)) }) : null
1759
+ ] }) });
1760
+ }
1761
+ var AVATAR = "size-[52px]";
1762
+ function iniciales(nombre) {
1763
+ return nombre.split(/\s+/).slice(0, 2).map((p) => p[0] ?? "").join("").toUpperCase();
1764
+ }
1765
+ function AuthorCard({ name, role, src, bio, action, className, ...props }) {
1766
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(SUPERFICIE_TARJETA, "p-lg gap-md flex items-start", className), ...props, children: [
1767
+ /* @__PURE__ */ jsxRuntime.jsxs(Avatar, { className: cn(AVATAR, "shrink-0"), children: [
1768
+ src ? /* @__PURE__ */ jsxRuntime.jsx(AvatarImage, { src, alt: "" }) : null,
1769
+ /* @__PURE__ */ jsxRuntime.jsx(AvatarFallback, { children: iniciales(name) })
1770
+ ] }),
1771
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "gap-xs flex min-w-0 flex-1 flex-col", children: [
1772
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { variant: "ui", as: "p", className: "font-medium", children: name }),
1773
+ role ? /* @__PURE__ */ jsxRuntime.jsx(Text, { variant: "chip", tone: "muted", as: "p", children: role }) : null,
1774
+ bio ? /* @__PURE__ */ jsxRuntime.jsx(Text, { variant: "ui", tone: "secondary", className: "mt-xs", children: bio }) : null,
1775
+ action ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-xs gap-sm flex flex-wrap items-center", children: action }) : null
1776
+ ] })
1777
+ ] });
1778
+ }
1779
+ function formatTime(seconds) {
1780
+ if (isNaN(seconds) || !isFinite(seconds)) return "0:00";
1781
+ const mins = Math.floor(seconds / 60);
1782
+ const secs = Math.floor(seconds % 60);
1783
+ return `${mins}:${secs.toString().padStart(2, "0")}`;
1784
+ }
1785
+ var WAVEFORM_HEIGHTS = [35, 65, 100, 65, 35];
1786
+ var RATES = [1, 1.25, 1.5, 1.75, 2];
1787
+ function Onda({ grosor, alto, sonando }) {
1788
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex items-end gap-[2px]", alto), "aria-hidden": "true", children: WAVEFORM_HEIGHTS.map((h, i) => /* @__PURE__ */ jsxRuntime.jsx(
1789
+ "span",
1790
+ {
1791
+ className: cn("rounded-pill bg-accent transition-standard", grosor),
1792
+ style: { height: `${h}%`, opacity: sonando ? 1 : 0.3 + h / 100 * 0.4 }
1793
+ },
1794
+ i
1795
+ )) });
1796
+ }
1797
+ function BarraProgreso({
1798
+ alto,
1799
+ perilla,
1800
+ progreso,
1801
+ redondeada = true,
1802
+ tabIndex = 0,
1803
+ ...puntero
1804
+ }) {
1805
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1806
+ "div",
1807
+ {
1808
+ className: cn(
1809
+ "group bg-surface-raised relative cursor-pointer",
1810
+ alto,
1811
+ redondeada && "rounded-pill"
1812
+ ),
1813
+ role: "slider",
1814
+ "aria-label": "Progreso del audio",
1815
+ "aria-valuemin": 0,
1816
+ "aria-valuemax": 100,
1817
+ "aria-valuenow": Math.round(progreso),
1818
+ tabIndex,
1819
+ ...puntero,
1820
+ children: [
1821
+ /* @__PURE__ */ jsxRuntime.jsx(
1822
+ "div",
1823
+ {
1824
+ className: cn("bg-accent absolute h-full", redondeada && "rounded-pill"),
1825
+ style: { width: `${progreso}%` }
1826
+ }
1827
+ ),
1828
+ /* @__PURE__ */ jsxRuntime.jsx(
1829
+ "div",
1830
+ {
1831
+ className: "rounded-pill bg-text-primary absolute top-1/2 -translate-y-1/2 opacity-0 transition-opacity group-hover:opacity-100",
1832
+ style: {
1833
+ width: perilla,
1834
+ height: perilla,
1835
+ left: `calc(${progreso}% - ${perilla / 2}px)`
1836
+ }
1837
+ }
1838
+ )
1839
+ ]
1840
+ }
1841
+ );
1842
+ }
1843
+ var CONTROL = "rounded-chip transition-standard cursor-pointer focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent";
1844
+ function BotonSalto({
1845
+ segundos,
1846
+ className,
1847
+ tamano,
1848
+ onSaltar
1849
+ }) {
1850
+ return /* @__PURE__ */ jsxRuntime.jsx(
1851
+ "button",
1852
+ {
1853
+ type: "button",
1854
+ onClick: () => onSaltar(segundos),
1855
+ className: cn("text-text-muted hover:text-text-primary", CONTROL, className),
1856
+ "aria-label": segundos < 0 ? "Retroceder 15 segundos" : "Adelantar 15 segundos",
1857
+ children: segundos < 0 ? /* @__PURE__ */ jsxRuntime.jsx(GoBackSeconds, { className: tamano }) : /* @__PURE__ */ jsxRuntime.jsx(AdvanceSeconds, { className: tamano })
1858
+ }
1859
+ );
1860
+ }
1861
+ function BotonVelocidad({
1862
+ className,
1863
+ velocidad,
1864
+ onCambiar
1865
+ }) {
1866
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1867
+ "button",
1868
+ {
1869
+ type: "button",
1870
+ onClick: onCambiar,
1871
+ className: cn(
1872
+ // `textMuted` sobre `surfaceRaised` da 4.07:1 en oscuro y no pasa AA.
1873
+ // El original del portafolio arrastra ese mismo fallo.
1874
+ "text-text-secondary hover:text-text-primary bg-surface-raised",
1875
+ CONTROL,
1876
+ className
1877
+ ),
1878
+ "aria-label": "Cambiar velocidad de reproducci\xF3n",
1879
+ children: [
1880
+ velocidad,
1881
+ "x"
1882
+ ]
1883
+ }
1884
+ );
1885
+ }
1886
+ function Volumen({
1887
+ tamano,
1888
+ ancho,
1889
+ silenciado,
1890
+ volumen,
1891
+ onSilenciar,
1892
+ onCambiarVolumen
1893
+ }) {
1894
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "gap-xs hidden items-center sm:flex", children: [
1895
+ /* @__PURE__ */ jsxRuntime.jsx(
1896
+ "button",
1897
+ {
1898
+ type: "button",
1899
+ onClick: onSilenciar,
1900
+ className: cn("text-text-muted hover:text-text-primary p-1", CONTROL),
1901
+ "aria-label": silenciado ? "Activar sonido" : "Silenciar",
1902
+ children: silenciado || volumen === 0 ? /* @__PURE__ */ jsxRuntime.jsx(VolumeMuted, { className: tamano }) : /* @__PURE__ */ jsxRuntime.jsx(VolumeOn, { className: tamano })
1903
+ }
1904
+ ),
1905
+ /* @__PURE__ */ jsxRuntime.jsx(
1906
+ "input",
1907
+ {
1908
+ type: "range",
1909
+ min: "0",
1910
+ max: "1",
1911
+ step: "0.1",
1912
+ value: silenciado ? 0 : volumen,
1913
+ onChange: onCambiarVolumen,
1914
+ className: cn(
1915
+ "bg-surface-raised rounded-pill h-1 cursor-pointer appearance-none",
1916
+ "[accent-color:var(--color-accent)]",
1917
+ ancho
1918
+ ),
1919
+ "aria-label": "Volumen"
1920
+ }
1921
+ )
1922
+ ] });
1923
+ }
1924
+ function IconoPlay({ className, cargando, error, sonando }) {
1925
+ if (cargando) return /* @__PURE__ */ jsxRuntime.jsx(Spinner, { className: cn("motion-safe:animate-spin", className) });
1926
+ if (error) return /* @__PURE__ */ jsxRuntime.jsx(Retry, { className });
1927
+ if (sonando) return /* @__PURE__ */ jsxRuntime.jsx(Pause, { className });
1928
+ return /* @__PURE__ */ jsxRuntime.jsx(Play, { className });
1929
+ }
1930
+ function BotonPlay({
1931
+ className,
1932
+ tamano,
1933
+ etiqueta,
1934
+ texto: texto2,
1935
+ onAlternar,
1936
+ ...estado
1937
+ }) {
1938
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1939
+ "button",
1940
+ {
1941
+ type: "button",
1942
+ onClick: onAlternar,
1943
+ className: cn(
1944
+ "text-accent-on transition-standard cursor-pointer",
1945
+ "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent",
1946
+ estado.error ? "bg-error hover:bg-error/80" : "bg-accent hover:bg-accent-hover",
1947
+ className
1948
+ ),
1949
+ "aria-label": etiqueta,
1950
+ children: [
1951
+ /* @__PURE__ */ jsxRuntime.jsx(IconoPlay, { className: tamano, ...estado }),
1952
+ texto2 ? /* @__PURE__ */ jsxRuntime.jsx("span", { children: texto2 }) : null
1953
+ ]
1954
+ }
1955
+ );
1956
+ }
1957
+ function AudioPlayer({ src, title, mode = "full", onFirstPlay }) {
1958
+ const audioRef = react.useRef(null);
1959
+ const staticRef = react.useRef(null);
1960
+ const isDragging = react.useRef(false);
1961
+ const hasTrackedPlay = react.useRef(false);
1962
+ const [isPlaying, setIsPlaying] = react.useState(false);
1963
+ const [currentTime, setCurrentTime] = react.useState(0);
1964
+ const [duration, setDuration] = react.useState(0);
1965
+ const [isLoading, setIsLoading] = react.useState(false);
1966
+ const [hasError, setHasError] = react.useState(false);
1967
+ const [volume, setVolume] = react.useState(1);
1968
+ const [isMuted, setIsMuted] = react.useState(false);
1969
+ const [playbackRate, setPlaybackRate] = react.useState(1);
1970
+ const [isStaticVisible, setIsStaticVisible] = react.useState(true);
1971
+ const flotante = mode === "banner" || mode === "compact";
1972
+ react.useEffect(() => {
1973
+ const audio = audioRef.current;
1974
+ if (!audio) return;
1975
+ const handleTimeUpdate = () => setCurrentTime(audio.currentTime);
1976
+ const handleLoadedMetadata = () => {
1977
+ setDuration(audio.duration);
1978
+ setIsLoading(false);
1979
+ setHasError(false);
1980
+ };
1981
+ const handleEnded = () => setIsPlaying(false);
1982
+ const handleWaiting = () => setIsLoading(true);
1983
+ const handleCanPlay = () => setIsLoading(false);
1984
+ const handleError = () => {
1985
+ setIsLoading(false);
1986
+ setHasError(true);
1987
+ setIsPlaying(false);
1988
+ };
1989
+ const handlePlaying = () => {
1990
+ setIsLoading(false);
1991
+ setHasError(false);
1992
+ };
1993
+ audio.addEventListener("timeupdate", handleTimeUpdate);
1994
+ audio.addEventListener("loadedmetadata", handleLoadedMetadata);
1995
+ audio.addEventListener("ended", handleEnded);
1996
+ audio.addEventListener("waiting", handleWaiting);
1997
+ audio.addEventListener("canplay", handleCanPlay);
1998
+ audio.addEventListener("error", handleError);
1999
+ audio.addEventListener("playing", handlePlaying);
2000
+ if (audio.readyState >= HTMLMediaElement.HAVE_METADATA) {
2001
+ setDuration(audio.duration);
2002
+ }
2003
+ return () => {
2004
+ audio.removeEventListener("timeupdate", handleTimeUpdate);
2005
+ audio.removeEventListener("loadedmetadata", handleLoadedMetadata);
2006
+ audio.removeEventListener("ended", handleEnded);
2007
+ audio.removeEventListener("waiting", handleWaiting);
2008
+ audio.removeEventListener("canplay", handleCanPlay);
2009
+ audio.removeEventListener("error", handleError);
2010
+ audio.removeEventListener("playing", handlePlaying);
2011
+ };
2012
+ }, []);
2013
+ react.useEffect(() => {
2014
+ if (!flotante || !staticRef.current) return;
2015
+ const observer = new IntersectionObserver(
2016
+ (entries) => {
2017
+ const entry = entries[0];
2018
+ if (entry) setIsStaticVisible(entry.isIntersecting);
2019
+ },
2020
+ { threshold: 0.1 }
2021
+ );
2022
+ observer.observe(staticRef.current);
2023
+ return () => observer.disconnect();
2024
+ }, [flotante]);
2025
+ const togglePlay = react.useCallback(async () => {
2026
+ const audio = audioRef.current;
2027
+ if (!audio) return;
2028
+ if (isPlaying) {
2029
+ audio.pause();
2030
+ setIsPlaying(false);
2031
+ } else {
2032
+ setIsLoading(true);
2033
+ setHasError(false);
2034
+ try {
2035
+ await audio.play();
2036
+ setIsPlaying(true);
2037
+ if (!hasTrackedPlay.current) {
2038
+ hasTrackedPlay.current = true;
2039
+ onFirstPlay?.(title);
2040
+ }
2041
+ } catch {
2042
+ setHasError(true);
2043
+ setIsPlaying(false);
2044
+ } finally {
2045
+ setIsLoading(false);
2046
+ }
2047
+ }
2048
+ }, [isPlaying, onFirstPlay, title]);
2049
+ const seekTo = react.useCallback(
2050
+ (e) => {
2051
+ const audio = audioRef.current;
2052
+ if (!audio) return;
2053
+ const rect = e.currentTarget.getBoundingClientRect();
2054
+ const position = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width));
2055
+ audio.currentTime = position * duration;
2056
+ },
2057
+ [duration]
2058
+ );
2059
+ const handlePointerDown = react.useCallback(
2060
+ (e) => {
2061
+ e.currentTarget.setPointerCapture(e.pointerId);
2062
+ isDragging.current = true;
2063
+ seekTo(e);
2064
+ },
2065
+ [seekTo]
2066
+ );
2067
+ const handlePointerMove = react.useCallback(
2068
+ (e) => {
2069
+ if (!isDragging.current) return;
2070
+ seekTo(e);
2071
+ },
2072
+ [seekTo]
2073
+ );
2074
+ const handlePointerUp = react.useCallback((e) => {
2075
+ e.currentTarget.releasePointerCapture(e.pointerId);
2076
+ isDragging.current = false;
2077
+ }, []);
2078
+ const handleVolumeChange = react.useCallback((e) => {
2079
+ const audio = audioRef.current;
2080
+ if (!audio) return;
2081
+ const newVolume = parseFloat(e.target.value);
2082
+ setVolume(newVolume);
2083
+ audio.volume = newVolume;
2084
+ setIsMuted(newVolume === 0);
2085
+ }, []);
2086
+ const toggleMute = react.useCallback(() => {
2087
+ const audio = audioRef.current;
2088
+ if (!audio) return;
2089
+ if (isMuted) {
2090
+ audio.volume = volume || 1;
2091
+ setIsMuted(false);
2092
+ } else {
2093
+ audio.volume = 0;
2094
+ setIsMuted(true);
2095
+ }
2096
+ }, [isMuted, volume]);
2097
+ const handlePlaybackRateChange = react.useCallback(() => {
2098
+ const audio = audioRef.current;
2099
+ if (!audio) return;
2100
+ const nextRate = RATES[(RATES.indexOf(playbackRate) + 1) % RATES.length] ?? 1;
2101
+ audio.playbackRate = nextRate;
2102
+ setPlaybackRate(nextRate);
2103
+ }, [playbackRate]);
2104
+ const skip = react.useCallback(
2105
+ (seconds) => {
2106
+ const audio = audioRef.current;
2107
+ if (!audio) return;
2108
+ audio.currentTime = Math.max(0, Math.min(audio.currentTime + seconds, duration));
2109
+ },
2110
+ [duration]
2111
+ );
2112
+ const progress = duration > 0 ? currentTime / duration * 100 : 0;
2113
+ const etiquetaPlay = hasError ? "Reintentar" : isPlaying ? "Pausar" : "Reproducir";
2114
+ const estadoPlay = { cargando: isLoading, error: hasError, sonando: isPlaying };
2115
+ const puntero = {
2116
+ onPointerDown: handlePointerDown,
2117
+ onPointerMove: handlePointerMove,
2118
+ onPointerUp: handlePointerUp
2119
+ };
2120
+ const flotanteJsx = /* @__PURE__ */ jsxRuntime.jsxs(
2121
+ "div",
2122
+ {
2123
+ "aria-hidden": isStaticVisible,
2124
+ className: cn(
2125
+ "fixed inset-x-0 bottom-0 z-40 xl:hidden",
2126
+ // Aparece y desaparece: el sistema no anima desplazamiento.
2127
+ isStaticVisible && "hidden"
2128
+ ),
2129
+ children: [
2130
+ /* @__PURE__ */ jsxRuntime.jsx(
2131
+ BarraProgreso,
2132
+ {
2133
+ alto: "h-1",
2134
+ perilla: 10,
2135
+ progreso: progress,
2136
+ redondeada: false,
2137
+ tabIndex: -1,
2138
+ ...puntero
2139
+ }
2140
+ ),
2141
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-surface/95 border-accent/25 border-t backdrop-blur-md", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "gap-sm px-md flex items-center py-5", children: [
2142
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "gap-xs flex shrink-0 items-center", children: [
2143
+ /* @__PURE__ */ jsxRuntime.jsx(Onda, { grosor: "w-[2px]", alto: "h-4", sonando: isPlaying }),
2144
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-eyebrow font-mono text-accent hidden uppercase sm:block", children: "Narraci\xF3n" })
2145
+ ] }),
2146
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
2147
+ title ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-label font-sans text-text-secondary truncate", children: title }) : null,
2148
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-chip font-mono text-text-muted tabular-nums", children: [
2149
+ formatTime(currentTime),
2150
+ " / ",
2151
+ formatTime(duration)
2152
+ ] })
2153
+ ] }),
2154
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [
2155
+ /* @__PURE__ */ jsxRuntime.jsx(BotonSalto, { segundos: -15, className: "p-1.5", tamano: "w-5 h-5", onSaltar: skip }),
2156
+ /* @__PURE__ */ jsxRuntime.jsx(
2157
+ BotonPlay,
2158
+ {
2159
+ className: "rounded-pill px-sm gap-xs flex items-center py-1.5",
2160
+ tamano: "w-4 h-4",
2161
+ etiqueta: etiquetaPlay,
2162
+ onAlternar: togglePlay,
2163
+ ...estadoPlay
2164
+ }
2165
+ ),
2166
+ /* @__PURE__ */ jsxRuntime.jsx(BotonSalto, { segundos: 15, className: "p-1.5", tamano: "w-5 h-5", onSaltar: skip }),
2167
+ /* @__PURE__ */ jsxRuntime.jsx(
2168
+ BotonVelocidad,
2169
+ {
2170
+ className: "text-label ml-0.5 px-1.5 py-0.5",
2171
+ velocidad: playbackRate,
2172
+ onCambiar: handlePlaybackRateChange
2173
+ }
2174
+ )
2175
+ ] })
2176
+ ] }) })
2177
+ ]
2178
+ }
2179
+ );
2180
+ if (mode === "banner") {
2181
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2182
+ /* @__PURE__ */ jsxRuntime.jsx("audio", { ref: audioRef, src, preload: "metadata" }),
2183
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: staticRef, children: [
2184
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "gap-sm mb-md flex items-center", children: [
2185
+ /* @__PURE__ */ jsxRuntime.jsx(Onda, { grosor: "w-[3px]", alto: "h-5", sonando: isPlaying }),
2186
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-eyebrow font-mono text-accent uppercase", children: "Narraci\xF3n de audio" }),
2187
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-chip font-mono text-text-muted ml-auto tabular-nums", children: [
2188
+ formatTime(currentTime),
2189
+ " / ",
2190
+ formatTime(duration)
2191
+ ] })
2192
+ ] }),
2193
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-md", children: /* @__PURE__ */ jsxRuntime.jsx(BarraProgreso, { alto: "h-1.5", perilla: 14, progreso: progress, ...puntero }) }),
2194
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "gap-sm flex items-center", children: [
2195
+ /* @__PURE__ */ jsxRuntime.jsx(BotonSalto, { segundos: -15, className: "p-2", tamano: "w-6 h-6", onSaltar: skip }),
2196
+ /* @__PURE__ */ jsxRuntime.jsx(
2197
+ BotonPlay,
2198
+ {
2199
+ className: "rounded-pill px-lg gap-xs text-ui flex items-center py-2 font-medium",
2200
+ tamano: "w-4 h-4",
2201
+ etiqueta: etiquetaPlay,
2202
+ texto: etiquetaPlay,
2203
+ onAlternar: togglePlay,
2204
+ ...estadoPlay
2205
+ }
2206
+ ),
2207
+ /* @__PURE__ */ jsxRuntime.jsx(BotonSalto, { segundos: 15, className: "p-2", tamano: "w-6 h-6", onSaltar: skip }),
2208
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "gap-sm ml-auto flex items-center", children: [
2209
+ /* @__PURE__ */ jsxRuntime.jsx(
2210
+ BotonVelocidad,
2211
+ {
2212
+ className: "text-label px-2 py-1",
2213
+ velocidad: playbackRate,
2214
+ onCambiar: handlePlaybackRateChange
2215
+ }
2216
+ ),
2217
+ /* @__PURE__ */ jsxRuntime.jsx(
2218
+ Volumen,
2219
+ {
2220
+ tamano: "w-4 h-4",
2221
+ ancho: "w-16",
2222
+ silenciado: isMuted,
2223
+ volumen: volume,
2224
+ onSilenciar: toggleMute,
2225
+ onCambiarVolumen: handleVolumeChange
2226
+ }
2227
+ )
2228
+ ] })
2229
+ ] })
2230
+ ] }),
2231
+ flotanteJsx
2232
+ ] });
2233
+ }
2234
+ if (mode === "compact") {
2235
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2236
+ /* @__PURE__ */ jsxRuntime.jsx("audio", { ref: audioRef, src, preload: "metadata" }),
2237
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: staticRef, className: "w-full", children: [
2238
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-xs", children: /* @__PURE__ */ jsxRuntime.jsx(BarraProgreso, { alto: "h-1.5", perilla: 12, progreso: progress, ...puntero }) }),
2239
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-chip font-mono text-text-muted mb-sm flex justify-between", children: [
2240
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: formatTime(currentTime) }),
2241
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: formatTime(duration) })
2242
+ ] }),
2243
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
2244
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
2245
+ /* @__PURE__ */ jsxRuntime.jsx(BotonSalto, { segundos: -15, className: "p-1.5", tamano: "w-5 h-5", onSaltar: skip }),
2246
+ /* @__PURE__ */ jsxRuntime.jsx(
2247
+ BotonPlay,
2248
+ {
2249
+ className: "rounded-pill flex size-[34px] items-center justify-center",
2250
+ tamano: "w-4 h-4",
2251
+ etiqueta: etiquetaPlay,
2252
+ onAlternar: togglePlay,
2253
+ ...estadoPlay
2254
+ }
2255
+ ),
2256
+ /* @__PURE__ */ jsxRuntime.jsx(BotonSalto, { segundos: 15, className: "p-1.5", tamano: "w-5 h-5", onSaltar: skip })
2257
+ ] }),
2258
+ /* @__PURE__ */ jsxRuntime.jsx(
2259
+ BotonVelocidad,
2260
+ {
2261
+ className: "text-label px-1.5 py-0.5",
2262
+ velocidad: playbackRate,
2263
+ onCambiar: handlePlaybackRateChange
2264
+ }
2265
+ )
2266
+ ] })
2267
+ ] }),
2268
+ flotanteJsx
2269
+ ] });
2270
+ }
2271
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-surface rounded-control border-border p-md w-full border", children: [
2272
+ /* @__PURE__ */ jsxRuntime.jsx("audio", { ref: audioRef, src, preload: "metadata" }),
2273
+ title ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-ui font-sans text-text-secondary mb-sm truncate", children: title }) : null,
2274
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-sm", children: /* @__PURE__ */ jsxRuntime.jsx(BarraProgreso, { alto: "h-2", perilla: 16, progreso: progress, ...puntero }) }),
2275
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-chip font-mono text-text-muted mb-sm flex justify-between", children: [
2276
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: formatTime(currentTime) }),
2277
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: formatTime(duration) })
2278
+ ] }),
2279
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
2280
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "gap-xs flex items-center", children: [
2281
+ /* @__PURE__ */ jsxRuntime.jsx(BotonSalto, { segundos: -15, className: "p-2", tamano: "w-5 h-5", onSaltar: skip }),
2282
+ /* @__PURE__ */ jsxRuntime.jsx(
2283
+ BotonPlay,
2284
+ {
2285
+ className: "rounded-pill flex size-12 items-center justify-center",
2286
+ tamano: "w-6 h-6",
2287
+ etiqueta: etiquetaPlay,
2288
+ onAlternar: togglePlay,
2289
+ ...estadoPlay
2290
+ }
2291
+ ),
2292
+ /* @__PURE__ */ jsxRuntime.jsx(BotonSalto, { segundos: 15, className: "p-2", tamano: "w-5 h-5", onSaltar: skip })
2293
+ ] }),
2294
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "gap-sm flex items-center", children: [
2295
+ /* @__PURE__ */ jsxRuntime.jsx(
2296
+ BotonVelocidad,
2297
+ {
2298
+ className: "text-label px-2 py-1",
2299
+ velocidad: playbackRate,
2300
+ onCambiar: handlePlaybackRateChange
2301
+ }
2302
+ ),
2303
+ /* @__PURE__ */ jsxRuntime.jsx(
2304
+ Volumen,
2305
+ {
2306
+ tamano: "w-5 h-5",
2307
+ ancho: "w-20",
2308
+ silenciado: isMuted,
2309
+ volumen: volume,
2310
+ onSilenciar: toggleMute,
2311
+ onCambiarVolumen: handleVolumeChange
2312
+ }
2313
+ )
2314
+ ] })
2315
+ ] })
2316
+ ] });
2317
+ }
2318
+ function Blockquote({ children, author, source, className, ...props }) {
2319
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2320
+ "blockquote",
2321
+ {
2322
+ className: cn("border-accent pl-md my-lg border-l-2", className),
2323
+ ...props,
2324
+ children: [
2325
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { variant: "body", tone: "secondary", children }),
2326
+ author || source ? /* @__PURE__ */ jsxRuntime.jsx("footer", { className: "mt-sm", children: /* @__PURE__ */ jsxRuntime.jsxs(Text, { variant: "label", tone: "muted", as: "span", children: [
2327
+ author ? /* @__PURE__ */ jsxRuntime.jsx("cite", { className: "not-italic", children: author }) : null,
2328
+ author && source ? " \xB7 " : null,
2329
+ source
2330
+ ] }) }) : null
2331
+ ]
2332
+ }
2333
+ );
2334
+ }
2335
+ var ENLACE = "transition-standard hover:text-accent focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent rounded-chip cursor-pointer";
2336
+ function Breadcrumb({
2337
+ items,
2338
+ homeHref = "/",
2339
+ homeLabel = "Inicio",
2340
+ linkAsChild,
2341
+ className,
2342
+ ...props
2343
+ }) {
2344
+ const enlace = (href, contenido) => linkAsChild ? /* @__PURE__ */ jsxRuntime.jsx(reactSlot.Slot, { className: ENLACE, children: linkAsChild({ href, children: contenido }) }) : /* @__PURE__ */ jsxRuntime.jsx("a", { href, className: ENLACE, children: contenido });
2345
+ return /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Ruta", className: cn("font-mono text-meta text-text-muted", className), ...props, children: /* @__PURE__ */ jsxRuntime.jsxs("ol", { className: "gap-xs flex flex-wrap items-center", children: [
2346
+ /* @__PURE__ */ jsxRuntime.jsx("li", { children: enlace(homeHref, /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-label": homeLabel, children: "~" })) }),
2347
+ items.map((item2, i) => {
2348
+ const ultimo = i === items.length - 1;
2349
+ return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "gap-xs flex items-center", children: [
2350
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", className: "text-border", children: "/" }),
2351
+ item2.href && !ultimo ? enlace(item2.href, item2.label) : /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-current": ultimo ? "page" : void 0, className: "text-text-secondary", children: item2.label })
2352
+ ] }, i);
2353
+ })
2354
+ ] }) });
2355
+ }
2356
+ function CodeBlock({ children, language, copyText, className, ...props }) {
2357
+ const [copiado, setCopiado] = react.useState(false);
2358
+ const temporizador = react.useRef(null);
2359
+ const copiar = react.useCallback(async () => {
2360
+ if (!copyText) return;
2361
+ try {
2362
+ await navigator.clipboard.writeText(copyText);
2363
+ setCopiado(true);
2364
+ if (temporizador.current) clearTimeout(temporizador.current);
2365
+ temporizador.current = setTimeout(() => setCopiado(false), 2e3);
2366
+ } catch {
2367
+ }
2368
+ }, [copyText]);
2369
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2370
+ "div",
2371
+ {
2372
+ "data-theme": "dark",
2373
+ className: cn(
2374
+ "rounded-card border-hairline bg-brand-hull overflow-hidden border",
2375
+ className
2376
+ ),
2377
+ ...props,
2378
+ children: [
2379
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-hairline px-sm flex items-center justify-between border-b py-1.5", children: [
2380
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-eyebrow font-mono text-text-muted uppercase", children: [
2381
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-accent", children: "\u276F" }),
2382
+ " ",
2383
+ language ?? "c\xF3digo"
2384
+ ] }),
2385
+ copyText ? /* @__PURE__ */ jsxRuntime.jsxs(
2386
+ "button",
2387
+ {
2388
+ type: "button",
2389
+ onClick: copiar,
2390
+ "aria-label": copiado ? "C\xF3digo copiado" : "Copiar c\xF3digo",
2391
+ "aria-live": "polite",
2392
+ className: cn(
2393
+ "gap-xs rounded-chip flex items-center px-2 py-1",
2394
+ "text-label font-mono text-text-muted cursor-pointer",
2395
+ "transition-standard hover:bg-surface hover:text-text-primary",
2396
+ "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent"
2397
+ ),
2398
+ children: [
2399
+ copiado ? /* @__PURE__ */ jsxRuntime.jsx(Check, { className: "text-accent" }) : /* @__PURE__ */ jsxRuntime.jsx(Copy, {}),
2400
+ copiado ? "Copiado" : "Copiar"
2401
+ ]
2402
+ }
2403
+ ) : null
2404
+ ] }),
2405
+ /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "p-md font-mono text-meta text-text-primary overflow-x-auto leading-relaxed", children })
2406
+ ]
2407
+ }
2408
+ );
2409
+ }
2410
+ function CourseCard({
2411
+ title,
2412
+ summary,
2413
+ meta,
2414
+ status,
2415
+ progress,
2416
+ className,
2417
+ ...props
2418
+ }) {
2419
+ return /* @__PURE__ */ jsxRuntime.jsx(Tarjeta, { className: cn("p-lg", className), ...props, children: /* @__PURE__ */ jsxRuntime.jsxs("article", { className: "gap-sm flex h-full flex-col", children: [
2420
+ status ? /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "warm", children: status }) }) : null,
2421
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { as: "h3", variant: "h3", className: "group-hover:text-accent transition-standard", children: title }),
2422
+ summary ? /* @__PURE__ */ jsxRuntime.jsx(Text, { variant: "ui", tone: "secondary", className: "line-clamp-3", children: summary }) : null,
2423
+ meta && meta.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(Text, { variant: "label", tone: "muted", as: "p", className: "gap-xs flex flex-wrap items-center", children: meta.map((m, i) => /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "gap-xs flex items-center", children: [
2424
+ i > 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: "\xB7" }) : null,
2425
+ m
2426
+ ] }, i)) }) : null,
2427
+ typeof progress === "number" ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "gap-xs mt-auto flex flex-col pt-sm", children: [
2428
+ /* @__PURE__ */ jsxRuntime.jsx(Progress, { value: progress, tone: "warm", label: `Progreso del curso: ${progress}%` }),
2429
+ /* @__PURE__ */ jsxRuntime.jsxs(Text, { variant: "label", tone: "muted", as: "p", children: [
2430
+ progress,
2431
+ "% cursado"
2432
+ ] })
2433
+ ] }) : null
2434
+ ] }) });
2435
+ }
2436
+
2437
+ // src/brand/catalogo.ts
2438
+ var caras = {
2439
+ annoyed: "face-annoyed.png",
2440
+ confused: "face-confused.png",
2441
+ hearts: "face-hearts.png",
2442
+ laughing: "face-laughing.png",
2443
+ shades: "face-shades.png",
2444
+ waiting: "face-waiting.png",
2445
+ wink: "face-wink.png"
2446
+ };
2447
+ var poses = {
2448
+ desk: "pose-desk.png",
2449
+ "laptop-coffee": "pose-laptop-coffee.png",
2450
+ peek: "pose-peek.png",
2451
+ surf: "pose-surf.png"
2452
+ };
2453
+ var aletas = {
2454
+ /** Dos azules. Para fondos claros. */
2455
+ color: "fin.png",
2456
+ /** Silueta a una tinta. Para fondos oscuros. */
2457
+ espuma: "fin-foam.png"
2458
+ };
2459
+ var usoDeCara = {
2460
+ wink: "Formularios, nota al pie amable",
2461
+ waiting: "Sin resultados, estado de espera",
2462
+ laughing: "\xC9xito, suscripci\xF3n confirmada",
2463
+ shades: "M\xF3dulo o curso completado",
2464
+ hearts: "Agradecimiento, OG de art\xEDculo",
2465
+ confused: "404, p\xE1gina no encontrada",
2466
+ annoyed: "Error del servidor, fallo de build"
2467
+ };
2468
+ var RUTA_ASSETS = "/brand";
2469
+ var listaCaras = Object.keys(caras);
2470
+ var listaPoses = Object.keys(poses);
2471
+ function Mascota({
2472
+ pose,
2473
+ basePath = RUTA_ASSETS,
2474
+ alt = "",
2475
+ className,
2476
+ ...props
2477
+ }) {
2478
+ return /* @__PURE__ */ jsxRuntime.jsx(
2479
+ "img",
2480
+ {
2481
+ src: `${basePath}/${poses[pose]}`,
2482
+ alt,
2483
+ className: cn("h-auto w-full max-w-64 select-none", className),
2484
+ ...props
2485
+ }
2486
+ );
2487
+ }
2488
+ function CaraDeMascota({
2489
+ expresion,
2490
+ basePath = RUTA_ASSETS,
2491
+ alt = "",
2492
+ className,
2493
+ ...props
2494
+ }) {
2495
+ return /* @__PURE__ */ jsxRuntime.jsx(
2496
+ "img",
2497
+ {
2498
+ src: `${basePath}/${caras[expresion]}`,
2499
+ alt,
2500
+ className: cn("h-auto w-full max-w-24 select-none", className),
2501
+ ...props
2502
+ }
2503
+ );
2504
+ }
2505
+ var CARA = "w-[66px] max-w-none";
2506
+ function EmptyState({
2507
+ expresion,
2508
+ title,
2509
+ description,
2510
+ action,
2511
+ basePath,
2512
+ className,
2513
+ ...props
2514
+ }) {
2515
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2516
+ "div",
2517
+ {
2518
+ className: cn(SUPERFICIE_TARJETA, "p-lg gap-sm flex flex-col items-center text-center", className),
2519
+ ...props,
2520
+ children: [
2521
+ /* @__PURE__ */ jsxRuntime.jsx(CaraDeMascota, { expresion, className: CARA, basePath }),
2522
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { variant: "ui", as: "p", className: "font-medium", children: title }),
2523
+ description ? /* @__PURE__ */ jsxRuntime.jsx(Text, { variant: "label", tone: "muted", as: "p", className: "max-w-measure font-normal", children: description }) : null,
2524
+ action ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-xs", children: action }) : null
2525
+ ]
2526
+ }
2527
+ );
2528
+ }
2529
+ function Footer({
2530
+ social,
2531
+ year = (/* @__PURE__ */ new Date()).getFullYear(),
2532
+ children,
2533
+ className,
2534
+ ...props
2535
+ }) {
2536
+ return /* @__PURE__ */ jsxRuntime.jsx("footer", { className: cn("border-hairline w-full border-t", className), ...props, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-wide px-md py-xl gap-lg mx-auto flex flex-col", children: [
2537
+ children ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "gap-md flex flex-wrap items-center", children }) : null,
2538
+ social && social.length > 0 ? (
2539
+ // 18px de separación, del documento. No es un escalón de `spacing`:
2540
+ // es el ritmo de una fila de iconos, no el de una página.
2541
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex items-center gap-[18px]", children: social.map((red) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(
2542
+ "a",
2543
+ {
2544
+ href: red.href,
2545
+ "aria-label": red.label,
2546
+ className: cn(
2547
+ "text-text-muted hover:text-accent transition-standard block cursor-pointer text-[19px]",
2548
+ "rounded-chip focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent"
2549
+ ),
2550
+ children: red.icon
2551
+ }
2552
+ ) }, red.href)) })
2553
+ ) : null,
2554
+ /* @__PURE__ */ jsxRuntime.jsxs(Text, { variant: "meta", tone: "muted", as: "p", children: [
2555
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { "aria-hidden": "true", className: "text-accent", children: [
2556
+ "$",
2557
+ " "
2558
+ ] }),
2559
+ "cd ~/",
2560
+ naming.domain,
2561
+ "/",
2562
+ year
2563
+ ] })
2564
+ ] }) });
2565
+ }
2566
+ function FooterLink({ asChild = false, className, ...props }) {
2567
+ const Raiz = asChild ? reactSlot.Slot : "a";
2568
+ return /* @__PURE__ */ jsxRuntime.jsx(
2569
+ Raiz,
2570
+ {
2571
+ className: cn(
2572
+ "font-mono text-meta text-text-secondary hover:text-accent transition-standard cursor-pointer",
2573
+ "rounded-chip focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent",
2574
+ className
2575
+ ),
2576
+ ...props
2577
+ }
2578
+ );
2579
+ }
2580
+ function Hero({
2581
+ title,
2582
+ eyebrow,
2583
+ description,
2584
+ action,
2585
+ pose,
2586
+ basePath,
2587
+ className,
2588
+ ...props
2589
+ }) {
2590
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2591
+ "section",
2592
+ {
2593
+ className: cn(
2594
+ "degradado-hero rounded-panel border-hairline relative overflow-hidden border",
2595
+ // 44 arriba, 40 a los lados y abajo. Del documento.
2596
+ "px-xl pt-[44px] pb-xl",
2597
+ className
2598
+ ),
2599
+ ...props,
2600
+ children: [
2601
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "gap-md flex flex-col md:max-w-[62%]", children: [
2602
+ eyebrow ? /* @__PURE__ */ jsxRuntime.jsx(Text, { variant: "eyebrow", tone: "accent", as: "p", children: eyebrow }) : null,
2603
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { as: "h1", variant: "display", children: title }),
2604
+ description ? /* @__PURE__ */ jsxRuntime.jsx(Text, { variant: "body", tone: "secondary", children: description }) : null,
2605
+ action ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "gap-sm mt-xs flex flex-wrap items-center", children: action }) : null
2606
+ ] }),
2607
+ pose ? /* @__PURE__ */ jsxRuntime.jsx(
2608
+ Mascota,
2609
+ {
2610
+ pose,
2611
+ basePath,
2612
+ className: cn(
2613
+ // En móvil, en el flujo y bajo los botones. Desde md, sangrando por
2614
+ // la esquina inferior derecha.
2615
+ "mt-lg mx-auto w-40",
2616
+ "md:mt-0 md:absolute md:right-0 md:-bottom-4 md:mx-0 md:w-64"
2617
+ )
2618
+ }
2619
+ ) : null
2620
+ ]
2621
+ }
2622
+ );
2623
+ }
2624
+ function LinkRow({
2625
+ name,
2626
+ description,
2627
+ icon,
2628
+ external = false,
2629
+ className,
2630
+ ...props
2631
+ }) {
2632
+ const rel = external ? "noopener noreferrer" : props.rel;
2633
+ const target = external ? "_blank" : props.target;
2634
+ return /* @__PURE__ */ jsxRuntime.jsx(
2635
+ Tarjeta,
2636
+ {
2637
+ className: cn("px-md py-sm", className),
2638
+ ...props,
2639
+ rel,
2640
+ ...target ? { target } : {},
2641
+ children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "gap-sm flex items-center", children: [
2642
+ icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-text-muted group-hover:text-accent transition-standard shrink-0 text-2xl", children: icon }) : null,
2643
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "min-w-0 flex-1", children: [
2644
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { as: "span", variant: "ui", className: "group-hover:text-accent transition-standard block font-medium", children: name }),
2645
+ description ? /* @__PURE__ */ jsxRuntime.jsx(Text, { as: "span", variant: "label", tone: "muted", className: "block truncate", children: description }) : null
2646
+ ] }),
2647
+ external ? /* @__PURE__ */ jsxRuntime.jsx(
2648
+ ArrowUpRight,
2649
+ {
2650
+ className: "text-text-muted group-hover:text-accent transition-standard shrink-0",
2651
+ "aria-hidden": "true"
2652
+ }
2653
+ ) : null
2654
+ ] })
2655
+ }
2656
+ );
2657
+ }
2658
+ function Nav({ brand: brand2, children, actions, className, ...props }) {
2659
+ return /* @__PURE__ */ jsxRuntime.jsx(
2660
+ "header",
2661
+ {
2662
+ className: cn(
2663
+ "sticky top-0 z-50 w-full",
2664
+ // abismo al 86 % con 14px de desenfoque detrás. El alfa va sobre el
2665
+ // token, así que sigue el modo: en claro es papel al 86 %.
2666
+ "bg-background/86 backdrop-blur-[14px]",
2667
+ "border-hairline border-b",
2668
+ className
2669
+ ),
2670
+ ...props,
2671
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-wide px-md h-nav gap-lg mx-auto flex items-center", children: [
2672
+ brand2 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0", children: brand2 }) : null,
2673
+ children ? /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Principal", className: "min-w-0 flex-1", children: /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "gap-md flex items-center", children }) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1" }),
2674
+ actions ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "gap-sm flex shrink-0 items-center", children: actions }) : null
2675
+ ] })
2676
+ }
2677
+ );
2678
+ }
2679
+ function NavItem({ active = false, asChild = false, className, children, ...props }) {
2680
+ const Raiz = asChild ? reactSlot.Slot : "a";
2681
+ return /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsxs(
2682
+ Raiz,
2683
+ {
2684
+ "aria-current": active ? "page" : void 0,
2685
+ className: cn(
2686
+ "font-mono text-meta transition-standard cursor-pointer",
2687
+ "rounded-chip focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent",
2688
+ active ? "text-accent underline decoration-1 underline-offset-4" : "text-text-secondary hover:text-accent",
2689
+ className
2690
+ ),
2691
+ ...props,
2692
+ children: [
2693
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", className: "text-text-muted", children: "./" }),
2694
+ children
2695
+ ]
2696
+ }
2697
+ ) });
2698
+ }
2699
+ function NewsletterForm({
2700
+ title,
2701
+ description,
2702
+ state = "reposo",
2703
+ onSubmitEmail,
2704
+ successMessage = "Ya est\xE1s dentro. Te llega un correo cada dos semanas, y nada m\xE1s.",
2705
+ errorMessage = "No se pudo suscribir ese correo. Rev\xEDsalo y vuelve a intentar.",
2706
+ disclaimer,
2707
+ expresion,
2708
+ basePath,
2709
+ submitLabel = "Suscribirme",
2710
+ placeholder = "tu@correo.dev",
2711
+ fieldLabel = "Correo electr\xF3nico",
2712
+ className,
2713
+ ...props
2714
+ }) {
2715
+ const id = react.useId();
2716
+ const enviando = state === "enviando";
2717
+ const error = state === "error";
2718
+ function enviar(evento) {
2719
+ evento.preventDefault();
2720
+ const datos = new FormData(evento.currentTarget);
2721
+ const correo = String(datos.get("email") ?? "");
2722
+ onSubmitEmail?.(correo);
2723
+ }
2724
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2725
+ "section",
2726
+ {
2727
+ className: cn(
2728
+ "degradado-seccion rounded-panel border-hairline p-lg gap-md flex flex-col border",
2729
+ className
2730
+ ),
2731
+ ...props,
2732
+ children: [
2733
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "gap-xs flex flex-col", children: [
2734
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { as: "h2", variant: "h3", children: title }),
2735
+ description ? /* @__PURE__ */ jsxRuntime.jsx(Text, { variant: "ui", tone: "secondary", children: description }) : null
2736
+ ] }),
2737
+ /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: enviar, className: "gap-sm flex flex-col sm:flex-row sm:items-end", noValidate: true, children: [
2738
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "gap-xs flex flex-1 flex-col", children: [
2739
+ /* @__PURE__ */ jsxRuntime.jsx(Label2, { htmlFor: id, children: fieldLabel }),
2740
+ /* @__PURE__ */ jsxRuntime.jsx(
2741
+ Input,
2742
+ {
2743
+ id,
2744
+ name: "email",
2745
+ type: "email",
2746
+ autoComplete: "email",
2747
+ required: true,
2748
+ placeholder,
2749
+ disabled: enviando,
2750
+ invalid: error,
2751
+ "aria-describedby": state === "exito" || error ? `${id}-aviso` : void 0
2752
+ }
2753
+ )
2754
+ ] }),
2755
+ /* @__PURE__ */ jsxRuntime.jsx(
2756
+ Button,
2757
+ {
2758
+ type: "submit",
2759
+ variant: "conversion",
2760
+ loading: enviando,
2761
+ className: "disabled:opacity-60",
2762
+ children: submitLabel
2763
+ }
2764
+ )
2765
+ ] }),
2766
+ state === "exito" ? /* @__PURE__ */ jsxRuntime.jsx(Alert, { id: `${id}-aviso`, variant: "success", enfasis: "fuerte", children: successMessage }) : null,
2767
+ error ? /* @__PURE__ */ jsxRuntime.jsx(Alert, { id: `${id}-aviso`, variant: "error", enfasis: "fuerte", children: errorMessage }) : null,
2768
+ disclaimer ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "gap-sm flex items-center", children: [
2769
+ expresion ? /* @__PURE__ */ jsxRuntime.jsx(CaraDeMascota, { expresion, basePath, className: "w-10 max-w-none" }) : null,
2770
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { variant: "label", tone: "muted", as: "p", className: "font-normal", children: disclaimer })
2771
+ ] }) : null
2772
+ ]
2773
+ }
2774
+ );
2775
+ }
2776
+ var cabecera = classVarianceAuthority.cva("gap-sm flex flex-col", {
2777
+ variants: {
2778
+ size: {
2779
+ display: "py-section",
2780
+ page: "py-xl"
2781
+ }
2782
+ },
2783
+ defaultVariants: { size: "page" }
2784
+ });
2785
+ function PageHeader({
2786
+ title,
2787
+ eyebrow,
2788
+ description,
2789
+ action,
2790
+ size: size2,
2791
+ as = "h1",
2792
+ className,
2793
+ ...props
2794
+ }) {
2795
+ return /* @__PURE__ */ jsxRuntime.jsxs("header", { className: cn(cabecera({ size: size2 }), className), ...props, children: [
2796
+ eyebrow ? /* @__PURE__ */ jsxRuntime.jsx(Text, { variant: "eyebrow", tone: "accent", as: "p", children: eyebrow }) : null,
2797
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { as, variant: size2 === "display" ? "display" : "h1", className: "max-w-measure", children: title }),
2798
+ description ? /* @__PURE__ */ jsxRuntime.jsx(Text, { variant: "body", tone: "secondary", children: description }) : null,
2799
+ action ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "gap-sm mt-sm flex flex-wrap items-center", children: action }) : null
2800
+ ] });
2801
+ }
2802
+ function SidebarItem({
2803
+ active = false,
2804
+ asChild = false,
2805
+ badge: badge2,
2806
+ className,
2807
+ children,
2808
+ ...props
2809
+ }) {
2810
+ const Raiz = asChild ? reactSlot.Slot : "a";
2811
+ return /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsxs(
2812
+ Raiz,
2813
+ {
2814
+ "aria-current": active ? "page" : void 0,
2815
+ className: cn(
2816
+ "rounded-chip px-sm gap-xs flex cursor-pointer items-center py-1.5",
2817
+ "font-mono text-meta transition-standard",
2818
+ "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent",
2819
+ // El activo es fondo `surfaceRaised` y tinta primaria, igual que
2820
+ // `TabsTrigger`. NO bioluz: `tokens.ts` lo dice explícito — acento
2821
+ // claro pasa sobre background y sobre surface, pero sobre
2822
+ // surfaceRaised mide 4.2 y no es color de texto ahí. El acento se
2823
+ // queda en el `▸`, que es decorativo y le aplica el umbral de 3:1.
2824
+ active ? "bg-surface-raised text-text-primary" : "text-text-secondary hover:text-text-primary hover:bg-surface-raised",
2825
+ className
2826
+ ),
2827
+ ...props,
2828
+ children: [
2829
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", className: active ? "text-accent" : "text-text-muted", children: "\u25B8" }),
2830
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate", children }),
2831
+ badge2 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-text-muted shrink-0", children: badge2 }) : null
2832
+ ]
2833
+ }
2834
+ ) });
2835
+ }
2836
+ function SidebarNav({
2837
+ title,
2838
+ version,
2839
+ branch,
2840
+ children,
2841
+ className,
2842
+ ...props
2843
+ }) {
2844
+ const pie = [version, branch].filter(Boolean);
2845
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2846
+ "nav",
2847
+ {
2848
+ "aria-label": typeof title === "string" ? title : "Administraci\xF3n",
2849
+ className: cn(
2850
+ "border-hairline bg-surface p-sm gap-sm flex h-full flex-col border-r",
2851
+ className
2852
+ ),
2853
+ ...props,
2854
+ children: [
2855
+ title ? /* @__PURE__ */ jsxRuntime.jsx(Text, { variant: "eyebrow", tone: "muted", as: "p", className: "px-sm", children: title }) : null,
2856
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "gap-0.5 flex flex-1 flex-col", children }),
2857
+ pie.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(Text, { variant: "meta", tone: "muted", as: "p", className: "border-hairline px-sm pt-sm border-t", children: pie.map((p, i) => /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
2858
+ i > 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: " \xB7 " }) : null,
2859
+ p
2860
+ ] }, i)) }) : null
2861
+ ]
2862
+ }
2863
+ );
2864
+ }
2865
+ function Stat({ value, label, tone = "neutral", progress, className, ...props }) {
2866
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(SUPERFICIE_TARJETA, "p-lg gap-xs flex flex-col", className), ...props, children: [
2867
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { variant: "stat", as: "p", tone: tone === "alerta" ? "warm" : "accent", children: value }),
2868
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { variant: "eyebrow", tone: "muted", as: "p", children: label }),
2869
+ typeof progress === "number" ? /* @__PURE__ */ jsxRuntime.jsx(
2870
+ Progress,
2871
+ {
2872
+ value: progress,
2873
+ tone: tone === "alerta" ? "warm" : "accent",
2874
+ label: `${label}: ${progress}%`,
2875
+ className: "mt-sm"
2876
+ }
2877
+ ) : null
2878
+ ] });
2879
+ }
2880
+ function TalkCard({
2881
+ title,
2882
+ event,
2883
+ date,
2884
+ dateTime,
2885
+ location,
2886
+ status,
2887
+ className,
2888
+ ...props
2889
+ }) {
2890
+ const pie = [
2891
+ date ? /* @__PURE__ */ jsxRuntime.jsx("time", { dateTime, children: date }, "fecha") : null,
2892
+ location ? /* @__PURE__ */ jsxRuntime.jsx("span", { children: location }, "lugar") : null
2893
+ ].filter(Boolean);
2894
+ return /* @__PURE__ */ jsxRuntime.jsx(Tarjeta, { className: cn("p-lg", className), ...props, children: /* @__PURE__ */ jsxRuntime.jsxs("article", { className: "gap-sm flex h-full flex-col", children: [
2895
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "gap-sm flex items-start justify-between", children: [
2896
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { variant: "eyebrow", tone: "accent", as: "p", children: event }),
2897
+ status ? /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "neutral", children: status }) : null
2898
+ ] }),
2899
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { as: "h3", variant: "h3", className: "group-hover:text-accent transition-standard", children: title }),
2900
+ pie.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(Text, { variant: "label", tone: "muted", as: "p", className: "gap-xs mt-auto flex items-center pt-sm", children: pie.map((m, i) => /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "gap-xs flex items-center", children: [
2901
+ i > 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: "\xB7" }) : null,
2902
+ m
2903
+ ] }, i)) }) : null
2904
+ ] }) });
2905
+ }
2906
+ function TableOfContents({
2907
+ items,
2908
+ title = "En esta p\xE1gina",
2909
+ activeHref,
2910
+ linkAsChild,
2911
+ className,
2912
+ ...props
2913
+ }) {
2914
+ return /* @__PURE__ */ jsxRuntime.jsxs("nav", { "aria-label": typeof title === "string" ? title : "En esta p\xE1gina", className: cn("gap-sm flex flex-col", className), ...props, children: [
2915
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { variant: "eyebrow", tone: "muted", as: "p", children: title }),
2916
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "border-hairline gap-xs flex flex-col border-l", children: items.map((item2) => {
2917
+ const activo = item2.href === activeHref;
2918
+ const clases = cn(
2919
+ "px-sm -ml-px block border-l",
2920
+ "font-sans text-label transition-standard",
2921
+ "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent",
2922
+ "cursor-pointer",
2923
+ item2.nested && "pl-lg",
2924
+ activo ? "border-accent text-accent" : "border-transparent text-text-secondary hover:text-text-primary"
2925
+ );
2926
+ return /* @__PURE__ */ jsxRuntime.jsx("li", { children: linkAsChild ? /* @__PURE__ */ jsxRuntime.jsx(reactSlot.Slot, { className: clases, "aria-current": activo ? "location" : void 0, children: linkAsChild({ href: item2.href, children: item2.label }) }) : /* @__PURE__ */ jsxRuntime.jsx("a", { href: item2.href, className: clases, "aria-current": activo ? "location" : void 0, children: item2.label }) }, item2.href);
2927
+ }) })
2928
+ ] });
2929
+ }
2930
+ function Isotipo({
2931
+ sobre = "oscuro",
2932
+ basePath = RUTA_ASSETS,
2933
+ alt = "",
2934
+ className,
2935
+ ...props
2936
+ }) {
2937
+ const archivo = sobre === "oscuro" ? aletas.espuma : aletas.color;
2938
+ return /* @__PURE__ */ jsxRuntime.jsx(
2939
+ "img",
2940
+ {
2941
+ src: `${basePath}/${archivo}`,
2942
+ alt,
2943
+ width: 147,
2944
+ height: 111,
2945
+ className: cn("h-8 w-auto select-none", className),
2946
+ ...props
2947
+ }
2948
+ );
2949
+ }
2950
+ function Logo({
2951
+ sobre = "oscuro",
2952
+ basePath = RUTA_ASSETS,
2953
+ soloIsotipo = false,
2954
+ className,
2955
+ ...props
2956
+ }) {
2957
+ return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("gap-xs inline-flex items-center", className), ...props, children: [
2958
+ /* @__PURE__ */ jsxRuntime.jsx(
2959
+ Isotipo,
2960
+ {
2961
+ sobre,
2962
+ basePath,
2963
+ alt: soloIsotipo ? naming.wordmark : "",
2964
+ className: "h-7 w-auto"
2965
+ }
2966
+ ),
2967
+ soloIsotipo ? null : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui font-display text-text-primary font-bold tracking-[-0.02em]", children: naming.wordmark })
2968
+ ] });
2969
+ }
2970
+
2971
+ // src/lib/social.tsx
2972
+ var social_exports = {};
2973
+ __export(social_exports, {
2974
+ Correo: () => Correo,
2975
+ Discord: () => Discord,
2976
+ GitHub: () => GitHub,
2977
+ Instagram: () => Instagram,
2978
+ LinkedIn: () => LinkedIn,
2979
+ Rss: () => Rss,
2980
+ X: () => X,
2981
+ YouTube: () => YouTube
2982
+ });
2983
+ function Marca({ children, ...props }) {
2984
+ return /* @__PURE__ */ jsxRuntime.jsx(
2985
+ "svg",
2986
+ {
2987
+ viewBox: "0 0 24 24",
2988
+ width: "1em",
2989
+ height: "1em",
2990
+ fill: "currentColor",
2991
+ "aria-hidden": "true",
2992
+ focusable: "false",
2993
+ ...props,
2994
+ children
2995
+ }
2996
+ );
2997
+ }
2998
+ function Funcional({ children, ...props }) {
2999
+ return /* @__PURE__ */ jsxRuntime.jsx(
3000
+ "svg",
3001
+ {
3002
+ viewBox: "0 0 24 24",
3003
+ width: "1em",
3004
+ height: "1em",
3005
+ fill: "none",
3006
+ stroke: "currentColor",
3007
+ strokeWidth: 1.6,
3008
+ strokeLinecap: "round",
3009
+ strokeLinejoin: "round",
3010
+ "aria-hidden": "true",
3011
+ focusable: "false",
3012
+ ...props,
3013
+ children
3014
+ }
3015
+ );
3016
+ }
3017
+ var GitHub = (props) => /* @__PURE__ */ jsxRuntime.jsx(Marca, { ...props, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 .5C5.73.5.5 5.73.5 12a11.5 11.5 0 0 0 7.86 10.91c.58.1.79-.25.79-.55 0-.27-.01-1.18-.02-2.14-3.2.7-3.88-1.36-3.88-1.36-.52-1.33-1.28-1.68-1.28-1.68-1.05-.72.08-.7.08-.7 1.16.08 1.77 1.19 1.77 1.19 1.03 1.77 2.7 1.26 3.36.96.1-.75.4-1.26.73-1.55-2.55-.29-5.24-1.28-5.24-5.69 0-1.26.45-2.29 1.19-3.09-.12-.29-.52-1.46.11-3.05 0 0 .97-.31 3.18 1.18a11 11 0 0 1 5.79 0c2.2-1.49 3.17-1.18 3.17-1.18.63 1.59.23 2.76.12 3.05.74.8 1.18 1.83 1.18 3.09 0 4.42-2.69 5.39-5.25 5.68.41.36.78 1.06.78 2.14 0 1.55-.01 2.79-.01 3.17 0 .3.2.66.79.55A11.5 11.5 0 0 0 23.5 12C23.5 5.73 18.27.5 12 .5Z" }) });
3018
+ var LinkedIn = (props) => /* @__PURE__ */ jsxRuntime.jsx(Marca, { ...props, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M4.98 3.5a2.5 2.5 0 1 1 0 5 2.5 2.5 0 0 1 0-5ZM3 9h4v12H3V9Zm7 0h3.8v1.71h.05a4.17 4.17 0 0 1 3.75-2.06c4.01 0 4.75 2.64 4.75 6.07V21h-4v-5.4c0-1.29-.02-2.95-1.8-2.95-1.8 0-2.08 1.4-2.08 2.85V21h-3.97V9Z" }) });
3019
+ var X = (props) => /* @__PURE__ */ jsxRuntime.jsx(Marca, { ...props, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M17.53 3h3.06l-6.69 7.64L21.75 21h-6.16l-4.83-6.3L5.25 21H2.19l7.15-8.17L2.5 3h6.32l4.36 5.77L17.53 3Zm-1.07 16.17h1.7L7.62 4.74H5.8l10.66 14.43Z" }) });
3020
+ var Instagram = (props) => /* @__PURE__ */ jsxRuntime.jsx(Marca, { ...props, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 2.16c3.2 0 3.58.01 4.85.07 1.17.05 1.8.25 2.23.41.56.22.96.48 1.38.9.42.42.68.82.9 1.38.16.42.36 1.06.41 2.23.06 1.27.07 1.65.07 4.85s-.01 3.58-.07 4.85c-.05 1.17-.25 1.8-.41 2.23-.22.56-.48.96-.9 1.38-.42.42-.82.68-1.38.9-.42.16-1.06.36-2.23.41-1.27.06-1.65.07-4.85.07s-3.58-.01-4.85-.07c-1.17-.05-1.8-.25-2.23-.41-.56-.22-.96-.48-1.38-.9-.42-.42-.68-.82-.9-1.38-.16-.42-.36-1.06-.41-2.23C2.17 15.58 2.16 15.2 2.16 12s.01-3.58.07-4.85c.05-1.17.25-1.8.41-2.23.22-.56.48-.96.9-1.38.42-.42.82-.68 1.38-.9.42-.16 1.06-.36 2.23-.41C8.42 2.17 8.8 2.16 12 2.16Zm0 3.68a6.16 6.16 0 1 0 0 12.32 6.16 6.16 0 0 0 0-12.32Zm0 10.16a4 4 0 1 1 0-8 4 4 0 0 1 0 8Zm7.85-10.4a1.44 1.44 0 1 1-2.88 0 1.44 1.44 0 0 1 2.88 0Z" }) });
3021
+ var Discord = (props) => /* @__PURE__ */ jsxRuntime.jsx(Marca, { ...props, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M20.32 5.56A18.5 18.5 0 0 0 15.7 4.1a.07.07 0 0 0-.07.04c-.2.36-.42.82-.58 1.19a17 17 0 0 0-5.1 0c-.16-.38-.39-.83-.59-1.19a.07.07 0 0 0-.07-.04c-1.6.28-3.15.77-4.62 1.46a.06.06 0 0 0-.03.03C1.66 10 .9 14.28 1.28 18.5a.08.08 0 0 0 .03.05 18.6 18.6 0 0 0 5.6 2.84.07.07 0 0 0 .08-.03c.43-.59.81-1.21 1.14-1.86a.07.07 0 0 0-.04-.1c-.6-.23-1.18-.51-1.74-.83a.07.07 0 0 1-.01-.12l.35-.27a.07.07 0 0 1 .07-.01 13.3 13.3 0 0 0 11.3 0 .07.07 0 0 1 .08.01l.34.27c.04.04.04.1-.01.12-.55.33-1.13.6-1.74.83a.07.07 0 0 0-.04.1c.34.65.72 1.27 1.14 1.86a.07.07 0 0 0 .08.03 18.5 18.5 0 0 0 5.6-2.84.07.07 0 0 0 .04-.05c.45-4.88-.75-9.12-3.18-12.88a.06.06 0 0 0-.03-.03ZM8.4 15.93c-1.1 0-2.01-1.01-2.01-2.25 0-1.24.89-2.25 2.01-2.25 1.13 0 2.03 1.02 2.02 2.25 0 1.24-.9 2.25-2.02 2.25Zm7.22 0c-1.1 0-2.01-1.01-2.01-2.25 0-1.24.89-2.25 2.01-2.25 1.13 0 2.03 1.02 2.02 2.25 0 1.24-.89 2.25-2.02 2.25Z" }) });
3022
+ var YouTube = (props) => /* @__PURE__ */ jsxRuntime.jsx(Marca, { ...props, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M23.5 6.9a3 3 0 0 0-2.12-2.12C19.5 4.27 12 4.27 12 4.27s-7.5 0-9.38.51A3 3 0 0 0 .5 6.9 31.3 31.3 0 0 0 0 12a31.3 31.3 0 0 0 .5 5.1 3 3 0 0 0 2.12 2.12c1.88.51 9.38.51 9.38.51s7.5 0 9.38-.51a3 3 0 0 0 2.12-2.12A31.3 31.3 0 0 0 24 12a31.3 31.3 0 0 0-.5-5.1ZM9.6 15.6V8.4l6.24 3.6-6.24 3.6Z" }) });
3023
+ var Rss = (props) => /* @__PURE__ */ jsxRuntime.jsxs(Funcional, { ...props, children: [
3024
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M4 11a9 9 0 0 1 9 9M4 4a16 16 0 0 1 16 16" }),
3025
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "5", cy: "19", r: "1.6", fill: "currentColor", stroke: "none" })
3026
+ ] });
3027
+ var Correo = (props) => /* @__PURE__ */ jsxRuntime.jsxs(Funcional, { ...props, children: [
3028
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "2.75", y: "4.75", width: "18.5", height: "14.5", rx: "2" }),
3029
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m3.5 7.5 7.4 5.2a2 2 0 0 0 2.2 0l7.4-5.2" })
3030
+ ] });
3031
+
3032
+ exports.Alert = Alert;
3033
+ exports.ArticleCard = ArticleCard;
3034
+ exports.AudioPlayer = AudioPlayer;
3035
+ exports.AuthorCard = AuthorCard;
3036
+ exports.Avatar = Avatar;
3037
+ exports.AvatarFallback = AvatarFallback;
3038
+ exports.AvatarImage = AvatarImage;
3039
+ exports.Badge = Badge;
3040
+ exports.Blockquote = Blockquote;
3041
+ exports.Breadcrumb = Breadcrumb;
3042
+ exports.Button = Button;
3043
+ exports.Calendar = Calendar;
3044
+ exports.CaraDeMascota = CaraDeMascota;
3045
+ exports.Card = Card;
3046
+ exports.CardContent = CardContent;
3047
+ exports.CardDescription = CardDescription;
3048
+ exports.CardFooter = CardFooter;
3049
+ exports.CardHeader = CardHeader;
3050
+ exports.CardTitle = CardTitle;
3051
+ exports.CategoryBadge = CategoryBadge;
3052
+ exports.Checkbox = Checkbox;
3053
+ exports.Code = Code;
3054
+ exports.CodeBlock = CodeBlock;
3055
+ exports.CourseCard = CourseCard;
3056
+ exports.DateField = DateField;
3057
+ exports.Dialog = Dialog;
3058
+ exports.DialogClose = DialogClose;
3059
+ exports.DialogContent = DialogContent;
3060
+ exports.DialogDescription = DialogDescription;
3061
+ exports.DialogFooter = DialogFooter;
3062
+ exports.DialogHeader = DialogHeader;
3063
+ exports.DialogOverlay = DialogOverlay;
3064
+ exports.DialogTitle = DialogTitle;
3065
+ exports.DialogTrigger = DialogTrigger;
3066
+ exports.DropdownMenu = DropdownMenu;
3067
+ exports.DropdownMenuCheckboxItem = DropdownMenuCheckboxItem;
3068
+ exports.DropdownMenuContent = DropdownMenuContent;
3069
+ exports.DropdownMenuGroup = DropdownMenuGroup;
3070
+ exports.DropdownMenuItem = DropdownMenuItem;
3071
+ exports.DropdownMenuLabel = DropdownMenuLabel;
3072
+ exports.DropdownMenuRadioGroup = DropdownMenuRadioGroup;
3073
+ exports.DropdownMenuRadioItem = DropdownMenuRadioItem;
3074
+ exports.DropdownMenuSeparator = DropdownMenuSeparator;
3075
+ exports.DropdownMenuSub = DropdownMenuSub;
3076
+ exports.DropdownMenuSubContent = DropdownMenuSubContent;
3077
+ exports.DropdownMenuSubTrigger = DropdownMenuSubTrigger;
3078
+ exports.DropdownMenuTrigger = DropdownMenuTrigger;
3079
+ exports.EmptyState = EmptyState;
3080
+ exports.Footer = Footer;
3081
+ exports.FooterLink = FooterLink;
3082
+ exports.HOVER_TARJETA = HOVER_TARJETA;
3083
+ exports.Hero = Hero;
3084
+ exports.Input = Input;
3085
+ exports.Isotipo = Isotipo;
3086
+ exports.Label = Label2;
3087
+ exports.LinkRow = LinkRow;
3088
+ exports.Logo = Logo;
3089
+ exports.Mascota = Mascota;
3090
+ exports.MetricBadge = MetricBadge;
3091
+ exports.Nav = Nav;
3092
+ exports.NavItem = NavItem;
3093
+ exports.NewsletterForm = NewsletterForm;
3094
+ exports.PageHeader = PageHeader;
3095
+ exports.Pagination = Pagination;
3096
+ exports.PaginationContent = PaginationContent;
3097
+ exports.PaginationEllipsis = PaginationEllipsis;
3098
+ exports.PaginationItem = PaginationItem;
3099
+ exports.PaginationLink = PaginationLink;
3100
+ exports.PaginationNext = PaginationNext;
3101
+ exports.PaginationPrevious = PaginationPrevious;
3102
+ exports.Popover = Popover;
3103
+ exports.PopoverAnchor = PopoverAnchor;
3104
+ exports.PopoverContent = PopoverContent;
3105
+ exports.PopoverTrigger = PopoverTrigger;
3106
+ exports.Progress = Progress;
3107
+ exports.RUTA_ASSETS = RUTA_ASSETS;
3108
+ exports.RadioGroup = RadioGroup2;
3109
+ exports.RadioGroupItem = RadioGroupItem;
3110
+ exports.SUPERFICIE_TARJETA = SUPERFICIE_TARJETA;
3111
+ exports.Select = Select;
3112
+ exports.SelectContent = SelectContent;
3113
+ exports.SelectGroup = SelectGroup;
3114
+ exports.SelectItem = SelectItem;
3115
+ exports.SelectLabel = SelectLabel;
3116
+ exports.SelectSeparator = SelectSeparator;
3117
+ exports.SelectTrigger = SelectTrigger;
3118
+ exports.SelectValue = SelectValue;
3119
+ exports.Separator = Separator3;
3120
+ exports.Sheet = Sheet;
3121
+ exports.SheetBody = SheetBody;
3122
+ exports.SheetClose = SheetClose;
3123
+ exports.SheetContent = SheetContent;
3124
+ exports.SheetDescription = SheetDescription;
3125
+ exports.SheetFooter = SheetFooter;
3126
+ exports.SheetHeader = SheetHeader;
3127
+ exports.SheetTitle = SheetTitle;
3128
+ exports.SheetTrigger = SheetTrigger;
3129
+ exports.SidebarItem = SidebarItem;
3130
+ exports.SidebarNav = SidebarNav;
3131
+ exports.Skeleton = Skeleton;
3132
+ exports.Stat = Stat;
3133
+ exports.Switch = Switch;
3134
+ exports.Table = Table;
3135
+ exports.TableBody = TableBody;
3136
+ exports.TableCaption = TableCaption;
3137
+ exports.TableCell = TableCell;
3138
+ exports.TableFooter = TableFooter;
3139
+ exports.TableHead = TableHead;
3140
+ exports.TableHeader = TableHeader;
3141
+ exports.TableOfContents = TableOfContents;
3142
+ exports.TableRow = TableRow;
3143
+ exports.Tabs = Tabs;
3144
+ exports.TabsContent = TabsContent;
3145
+ exports.TabsList = TabsList;
3146
+ exports.TabsTrigger = TabsTrigger;
3147
+ exports.TalkCard = TalkCard;
3148
+ exports.Text = Text;
3149
+ exports.Textarea = Textarea;
3150
+ exports.Toast = Toast;
3151
+ exports.ToastAction = ToastAction;
3152
+ exports.ToastDescription = ToastDescription;
3153
+ exports.ToastProvider = ToastProvider;
3154
+ exports.ToastTitle = ToastTitle;
3155
+ exports.ToastViewport = ToastViewport;
3156
+ exports.Tooltip = Tooltip;
3157
+ exports.TooltipContent = TooltipContent;
3158
+ exports.TooltipProvider = TooltipProvider;
3159
+ exports.TooltipTrigger = TooltipTrigger;
3160
+ exports.alertVariants = alert;
3161
+ exports.aletas = aletas;
3162
+ exports.avatarVariants = avatar;
3163
+ exports.badgeVariants = badge;
3164
+ exports.brand = brand;
3165
+ exports.buttonVariants = button;
3166
+ exports.caras = caras;
3167
+ exports.categoryBadgeVariants = categoria;
3168
+ exports.cn = cn;
3169
+ exports.colors = colors;
3170
+ exports.control = control;
3171
+ exports.dark = dark;
3172
+ exports.fonts = fonts;
3173
+ exports.gradient = gradient;
3174
+ exports.light = light;
3175
+ exports.limits = limits;
3176
+ exports.listaCaras = listaCaras;
3177
+ exports.listaPoses = listaPoses;
3178
+ exports.motion = motion;
3179
+ exports.naming = naming;
3180
+ exports.poses = poses;
3181
+ exports.radius = radius;
3182
+ exports.shadow = shadow;
3183
+ exports.sintaxis = sintaxis;
3184
+ exports.size = size;
3185
+ exports.social = social_exports;
3186
+ exports.spacing = spacing;
3187
+ exports.tagline = tagline;
3188
+ exports.textVariants = texto;
3189
+ exports.tokens = tokens;
3190
+ exports.typeScale = typeScale;
3191
+ exports.usoDeCara = usoDeCara;