@eduardoalvarez/arrecife 0.5.1 → 0.7.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 (78) hide show
  1. package/CHANGELOG.md +114 -0
  2. package/README.md +868 -467
  3. package/dist/brand/index.cjs +112 -95
  4. package/dist/brand/index.d.cts +40 -39
  5. package/dist/brand/index.d.ts +40 -39
  6. package/dist/brand/index.js +5 -4
  7. package/dist/catalog-D13txprv.d.cts +78 -0
  8. package/dist/catalog-D13txprv.d.ts +78 -0
  9. package/dist/chart/index.cjs +100 -83
  10. package/dist/chart/index.d.cts +66 -66
  11. package/dist/chart/index.d.ts +66 -66
  12. package/dist/chart/index.js +14 -12
  13. package/dist/chunk-2WPWEIMD.js +27 -0
  14. package/dist/chunk-45HVCTB7.js +70 -0
  15. package/dist/{chunk-ZEOQKRQ7.js → chunk-727HCBD4.js} +1 -1
  16. package/dist/chunk-CKRSQPTX.js +36 -0
  17. package/dist/chunk-E6KFUSKB.js +144 -0
  18. package/dist/chunk-GCRII2KQ.js +86 -0
  19. package/dist/{chunk-YZ2SDOVZ.js → chunk-JN3IS5OS.js} +30 -30
  20. package/dist/chunk-ODBFN44D.js +45 -0
  21. package/dist/chunk-OMKSESQB.js +300 -0
  22. package/dist/{chunk-VPT32GPG.js → chunk-TA7TLWW4.js} +2 -2
  23. package/dist/chunk-WGNIRIN7.js +42 -0
  24. package/dist/doctor.mjs +166 -0
  25. package/dist/form/index.cjs +109 -92
  26. package/dist/form/index.d.cts +43 -42
  27. package/dist/form/index.d.ts +43 -42
  28. package/dist/form/index.js +25 -23
  29. package/dist/icons/index.cjs +149 -0
  30. package/dist/icons/index.d.cts +94 -0
  31. package/dist/icons/index.d.ts +94 -0
  32. package/dist/icons/index.js +28 -0
  33. package/dist/index-DlAO2JZs.d.cts +47 -0
  34. package/dist/index-DlAO2JZs.d.ts +47 -0
  35. package/dist/index.cjs +1292 -983
  36. package/dist/index.d.cts +927 -806
  37. package/dist/index.d.ts +927 -806
  38. package/dist/index.js +809 -778
  39. package/dist/{label-DuTvJGxD.d.ts → label-MgHFKnFy.d.cts} +3 -3
  40. package/dist/{label-DuTvJGxD.d.cts → label-MgHFKnFy.d.ts} +3 -3
  41. package/dist/og/index.cjs +133 -132
  42. package/dist/og/index.d.cts +93 -89
  43. package/dist/og/index.d.ts +93 -89
  44. package/dist/og/index.js +106 -106
  45. package/dist/shiki/index.cjs +28 -30
  46. package/dist/shiki/index.d.cts +4 -4
  47. package/dist/shiki/index.d.ts +4 -4
  48. package/dist/shiki/index.js +12 -12
  49. package/dist/social/index.cjs +67 -0
  50. package/dist/social/index.d.cts +2 -0
  51. package/dist/social/index.d.ts +2 -0
  52. package/dist/social/index.js +2 -0
  53. package/dist/theme/index.cjs +97 -0
  54. package/dist/theme/index.d.cts +144 -0
  55. package/dist/theme/index.d.ts +144 -0
  56. package/dist/theme/index.js +2 -0
  57. package/dist/tokens/index.cjs +159 -88
  58. package/dist/tokens/index.d.cts +277 -165
  59. package/dist/tokens/index.d.ts +277 -165
  60. package/dist/tokens/index.js +2 -2
  61. package/dist/tokens/theme.css +165 -100
  62. package/dist/variants/index.cjs +195 -0
  63. package/dist/variants/index.d.cts +195 -0
  64. package/dist/variants/index.d.ts +195 -0
  65. package/dist/variants/index.js +3 -0
  66. package/llms.txt +1145 -746
  67. package/package.json +42 -11
  68. package/dist/catalogo-Du5ID-Hi.d.cts +0 -77
  69. package/dist/catalogo-Du5ID-Hi.d.ts +0 -77
  70. package/dist/chunk-E3OMP2DL.js +0 -36
  71. package/dist/chunk-KPZNNMV5.js +0 -83
  72. package/dist/chunk-NHS7ETKJ.js +0 -27
  73. package/dist/chunk-TSPJOM6K.js +0 -229
  74. package/dist/chunk-UOWIDFCB.js +0 -81
  75. package/dist/tema/index.cjs +0 -94
  76. package/dist/tema/index.d.cts +0 -110
  77. package/dist/tema/index.d.ts +0 -110
  78. package/dist/tema/index.js +0 -2
@@ -1,31 +1,32 @@
1
1
  /**
2
- * Arrecife — fuente única de la identidad visual.
2
+ * Arrecife — the single source of the visual identity.
3
3
  *
4
- * LA RESTRICCIÓN QUE MANDA SOBRE TODO LO DEMÁS: este archivo no importa nada.
5
- * Ni React, ni componentes, ni CSS de terceros. Lo consumen los cinco proyectos,
6
- * un generador de OG con Satori y un sitio Astro que no monta React. Si un token
7
- * termina dependiendo de un componente, la librería dejó de ser portable.
8
- * `scripts/check-tokens-purity.mjs` lo verifica en cada build.
4
+ * THE CONSTRAINT THAT OUTRANKS EVERYTHING ELSE: this file imports nothing. Not
5
+ * React, not components, not third-party CSS. It is consumed by the five
6
+ * projects, by an OG generator running on Satori and by an Astro site that
7
+ * never mounts React. The moment a token depends on a component, the library
8
+ * has stopped being portable. `scripts/check-tokens-purity.mjs` verifies it on
9
+ * every build.
9
10
  *
10
- * Los contrastes están MEDIDOS, no estimados. No cambies un hex para que
11
- * «combine mejor»: #0F8F80 (3.57:1) y #B4632A (3.95:1) ya se corrigieron por no
12
- * pasar AA sobre papel. Si los ves en algún lado, están mal.
11
+ * Contrast ratios here are MEASURED, not estimated. Do not nudge a hex so it
12
+ * «looks better»: #0F8F80 (3.57:1) and #B4632A (3.95:1) were already corrected
13
+ * for failing AA on paper. If you see them anywhere, they are wrong.
13
14
  *
14
- * Segunda corrección, por la misma razón. El documento medía todo contra
15
- * `background`, pero `surfaceRaised` es el peor caso en los DOS modos: en claro
16
- * es más oscuro que el fondo de página, en oscuro es más claro. Es donde viven
17
- * menús y tabs activos, así que es donde de verdad hay que poder leer.
15
+ * A second correction, for the same reason. The identity document measured
16
+ * everything against `background`, but `surfaceRaised` is the worst case in
17
+ * BOTH modes: in light it is darker than the page, in dark it is lighter. It is
18
+ * where menus and active tabs live, so it is where reading has to work.
18
19
  *
19
- * textMuted claro #6B7480 → #626A75 4.24 → 4.90 sobre background
20
- * warning claro #9A6A12 → #8D6111 4.23 → 4.88 sobre background
21
- * error oscuro #E05252 → #E15757 4.35 → 4.51 sobre surface
20
+ * textMuted light #6B7480 → #626A75 4.24 → 4.90 over background
21
+ * warning light #9A6A12 → #8D6111 4.23 → 4.88 over background
22
+ * error dark #E05252 → #E15757 4.35 → 4.51 over surface
22
23
  *
23
- * Los tres conservan tono y saturación exactos: solo baja o sube la luminosidad
24
- * entre 1 y 4 puntos. `accent` y `warm` claros se quedan como están: pasan sobre
25
- * background y sobre surface, y no son color de texto sobre surfaceRaised.
24
+ * All three keep their exact hue and saturation: only lightness moves, by one
25
+ * to four points. Light `accent` and `warm` stay as they are — they pass over
26
+ * background and over surface, and neither is a text color on surfaceRaised.
26
27
  */
27
28
  /**
28
- * Modo oscuro (primario). Contrastes medidos sobre `background` #091319.
29
+ * Dark mode (primary). Contrast measured against `background` #091319.
29
30
  */
30
31
  declare const dark: {
31
32
  readonly background: "#091319";
@@ -46,10 +47,25 @@ declare const dark: {
46
47
  readonly success: "#4FB477";
47
48
  readonly warning: "#E8A33D";
48
49
  readonly error: "#E15757";
50
+ /**
51
+ * The destructive fill. It is NOT `error`, and the difference is the role.
52
+ *
53
+ * `error` is a TEXT color: it has to read against a dark surface, so it sits
54
+ * mid-red. `danger` is a FILL: what has to read is the ink ON TOP of it, so it
55
+ * goes lighter. Same reasoning as `accent` and `accentOn` — one is measured
56
+ * against the page, the other against what it carries.
57
+ *
58
+ * Measured: ink 6.53:1 over the fill and 7.92:1 over the hover; the fill
59
+ * itself 6.71:1 over abyss, 5.94 over surface and 4.91 over surfaceRaised, so
60
+ * the outline variant reads as text on all three.
61
+ */
62
+ readonly danger: "#F4736B";
63
+ readonly dangerHover: "#F78D86";
64
+ readonly dangerOn: "#2B0A08";
49
65
  };
50
66
  /**
51
- * Modo claro. Contrastes medidos sobre `background` #F6F2EA.
52
- * `background` es blanco CÁLIDO: nunca #FFF como fondo de página.
67
+ * Light mode. Contrast measured against `background` #F6F2EA.
68
+ * `background` is WARM white: never #FFF as the page background.
53
69
  */
54
70
  declare const light: {
55
71
  readonly background: "#F6F2EA";
@@ -70,6 +86,20 @@ declare const light: {
70
86
  readonly success: "#0F6B52";
71
87
  readonly warning: "#8D6111";
72
88
  readonly error: "#C0392B";
89
+ /**
90
+ * In light mode `danger` and `error` land on the same hex, and that is not an
91
+ * oversight: over paper a red dark enough to carry white ink is also the red
92
+ * that reads as text. In dark they part company because the fill has to be
93
+ * lighter than the text color, not darker.
94
+ *
95
+ * Measured: ink 5.11:1 over the fill and 6.61:1 over the hover; the fill
96
+ * itself 4.87:1 over paper, 5.44 over surface and 4.50 over surfaceRaised —
97
+ * the last one is exactly on the AA line, which is where every light semantic
98
+ * in this palette sits.
99
+ */
100
+ readonly danger: "#C0392B";
101
+ readonly dangerHover: "#A32F22";
102
+ readonly dangerOn: "#FFF6F4";
73
103
  };
74
104
  declare const colors: {
75
105
  readonly dark: {
@@ -91,6 +121,21 @@ declare const colors: {
91
121
  readonly success: "#4FB477";
92
122
  readonly warning: "#E8A33D";
93
123
  readonly error: "#E15757";
124
+ /**
125
+ * The destructive fill. It is NOT `error`, and the difference is the role.
126
+ *
127
+ * `error` is a TEXT color: it has to read against a dark surface, so it sits
128
+ * mid-red. `danger` is a FILL: what has to read is the ink ON TOP of it, so it
129
+ * goes lighter. Same reasoning as `accent` and `accentOn` — one is measured
130
+ * against the page, the other against what it carries.
131
+ *
132
+ * Measured: ink 6.53:1 over the fill and 7.92:1 over the hover; the fill
133
+ * itself 6.71:1 over abyss, 5.94 over surface and 4.91 over surfaceRaised, so
134
+ * the outline variant reads as text on all three.
135
+ */
136
+ readonly danger: "#F4736B";
137
+ readonly dangerHover: "#F78D86";
138
+ readonly dangerOn: "#2B0A08";
94
139
  };
95
140
  readonly light: {
96
141
  readonly background: "#F6F2EA";
@@ -111,23 +156,37 @@ declare const colors: {
111
156
  readonly success: "#0F6B52";
112
157
  readonly warning: "#8D6111";
113
158
  readonly error: "#C0392B";
159
+ /**
160
+ * In light mode `danger` and `error` land on the same hex, and that is not an
161
+ * oversight: over paper a red dark enough to carry white ink is also the red
162
+ * that reads as text. In dark they part company because the fill has to be
163
+ * lighter than the text color, not darker.
164
+ *
165
+ * Measured: ink 5.11:1 over the fill and 6.61:1 over the hover; the fill
166
+ * itself 4.87:1 over paper, 5.44 over surface and 4.50 over surfaceRaised —
167
+ * the last one is exactly on the AA line, which is where every light semantic
168
+ * in this palette sits.
169
+ */
170
+ readonly danger: "#C0392B";
171
+ readonly dangerHover: "#A32F22";
172
+ readonly dangerOn: "#FFF6F4";
114
173
  };
115
174
  };
116
- /** Marca — iguales en los dos modos. */
175
+ /** Brand — identical in both modes. */
117
176
  declare const brand: {
118
- /** Cuerpo de la mascota. 4.22:1 → SOLO relleno, NUNCA texto. */
177
+ /** The mascot's body. 4.22:1 → FILL ONLY, NEVER text. */
119
178
  readonly body: "#3E7CB1";
120
- /** Patrón de manchas. */
179
+ /** Spot pattern. */
121
180
  readonly spots: "#C2D7E7";
122
- /** Casco · contorno y fondo de bloques de código. */
181
+ /** Hull · outline, and the background of code blocks. */
123
182
  readonly hull: "#0B1524";
124
183
  };
125
184
  declare const fonts: {
126
- /** SOLO titulares y números grandes. Nunca cuerpo. */
185
+ /** Headlines and large numbers ONLY. Never body copy. */
127
186
  readonly display: "\"Bricolage Grotesque\", ui-sans-serif, system-ui, sans-serif";
128
- /** Cuerpo e interfaz. */
187
+ /** Body and interface. */
129
188
  readonly sans: "\"Geist\", ui-sans-serif, system-ui, sans-serif";
130
- /** Código, rutas, etiquetas, metadatos, firma CLI. */
189
+ /** Code, paths, labels, metadata, the CLI signature. */
131
190
  readonly mono: "\"JetBrains Mono\", ui-monospace, SFMono-Regular, Menlo, monospace";
132
191
  };
133
192
  declare const typeScale: {
@@ -138,7 +197,7 @@ declare const typeScale: {
138
197
  readonly weight: 800;
139
198
  readonly tracking: "-0.035em";
140
199
  };
141
- /** Métricas grandes. Números, no prosa: interlineado 1 y sin descendentes. */
200
+ /** Large metrics. Numbers, not prose: line height 1 and no descenders. */
142
201
  readonly stat: {
143
202
  readonly family: "display";
144
203
  readonly size: 46;
@@ -174,12 +233,12 @@ declare const typeScale: {
174
233
  readonly weight: 400;
175
234
  };
176
235
  /**
177
- * 17px. El botón grande y la bajada de las páginas internas.
236
+ * 17px. The large button, and the deck on interior pages.
178
237
  *
179
- * Entra como escalón propio porque el documento lo usa DOS veces y en piezas
180
- * distintas: «lg 15px 30px r12» con texto de 17, y «h1 44/700 · bajada 17px ·
181
- * párrafo de contexto 15px». Un solo uso no habría justificado partir la
182
- * distancia entre `ui` (15) y `body` (18); dos sí.
238
+ * It earns its own step because the identity document uses it TWICE, in two
239
+ * different pieces: «lg 15/30 r12» with 17px text, and «h1 44/700 · deck 17px
240
+ * · context paragraph 15px». One use would not have justified splitting the
241
+ * gap between `ui` (15) and `body` (18); two did.
183
242
  */
184
243
  readonly lead: {
185
244
  readonly family: "sans";
@@ -200,11 +259,11 @@ declare const typeScale: {
200
259
  readonly weight: 500;
201
260
  };
202
261
  /**
203
- * La escala de las etiquetas de estado: sans 12.5/500, cuadrada.
262
+ * The status-badge scale: sans 12.5/500, squared off.
204
263
  *
205
- * Es medio píxel por debajo de `label`, y esta vez el medio píxel sí importa:
206
- * una etiqueta de estado va dentro de una tabla o al lado de un título, y a 13
207
- * competía con el texto que acompaña. El documento la da en 12.5 y se ve.
264
+ * That is half a pixel below `label`, and this time the half pixel matters: a
265
+ * status badge sits inside a table or next to a title, and at 13 it competed
266
+ * with the text it accompanies. The document specifies 12.5 and it shows.
208
267
  */
209
268
  readonly tag: {
210
269
  readonly family: "sans";
@@ -213,15 +272,15 @@ declare const typeScale: {
213
272
  readonly weight: 500;
214
273
  };
215
274
  /**
216
- * La escala de categoría y métrica: mono 11.5.
275
+ * The category and metric scale: mono 11.5.
217
276
  *
218
- * Rompe el suelo de `limits.minScreenPx`, y es a propósito. Ese suelo protege
219
- * al TEXTO —lo que se lee en una frase—, y una píldora de una palabra no es
220
- * texto corrido: es una marca. El contraste sigue medido y pasa AA (plancton
221
- * 5.57:1 sobre abismo), que es la parte que no se negocia.
277
+ * It breaks the floor set by `limits.minScreenPx`, deliberately. That floor
278
+ * protects TEXT — what you read in a sentence — and a one-word pill is not
279
+ * running text: it is a mark. Contrast is still measured and still passes AA
280
+ * (plankton 5.57:1 over abyss), which is the part that is not negotiable.
222
281
  *
223
- * A 13 las tres familias de etiqueta salían del tamaño de un botón pequeño y
224
- * pesaban más que el título que acompañan. Ver `docs/decisiones.md`.
282
+ * At 13 the three badge families grew past the size of a small button and
283
+ * outweighed the title they accompany. See `docs/decisions.md`.
225
284
  */
226
285
  readonly chip: {
227
286
  readonly family: "mono";
@@ -230,18 +289,18 @@ declare const typeScale: {
230
289
  readonly weight: 400;
231
290
  };
232
291
  /**
233
- * Mono SIN transformar: fechas, rutas, versiones, nombres de archivo, la firma
234
- * del footer y las métricas de etiqueta. Es la mayoría del mono del sistema.
292
+ * Mono with NO transform: dates, paths, versions, file names, the footer
293
+ * signature and metric labels. It is most of the mono in the system.
235
294
  *
236
- * Existe porque `eyebrow` lleva `uppercase` de fábrica y no es una preferencia
237
- * que se pueda apagar: es la escala del eyebrow. Un `18 ago 2026` en versalitas
238
- * o un `pose-laptop-coffee.png` en mayúsculas están mal, y sin este escalón la
239
- * única salida era un `normal-case` en cada sitio de uso.
295
+ * It exists because `eyebrow` ships `uppercase` and that is not a preference
296
+ * you can switch off: it IS the eyebrow scale. An `18 Aug 2026` in small caps
297
+ * or a `pose-laptop-coffee.png` in all caps are wrong, and without this step
298
+ * the only way out was a `normal-case` at every call site.
240
299
  *
241
- * El documento dice 12.5. Son 13 por la misma razón por la que `textMuted` se
242
- * corrigió: `limits.minScreenPx` es 13 y plancton «nunca bajo 13px». Esta
243
- * escala es justo donde se escriben las metas en muted, así que ponerla en
244
- * 12.5 habría dejado ilegible su uso más común por medio píxel.
300
+ * The document says 12.5. This is 13 for the same reason `textMuted` was
301
+ * corrected: `limits.minScreenPx` is 13 and plankton is «never under 13px».
302
+ * This scale is exactly where muted metadata gets written, so putting it at
303
+ * 12.5 would have made its most common use illegible by half a pixel.
245
304
  */
246
305
  readonly meta: {
247
306
  readonly family: "mono";
@@ -256,13 +315,13 @@ declare const typeScale: {
256
315
  readonly transform: "uppercase";
257
316
  };
258
317
  };
259
- /** Límites duros de legibilidad. */
318
+ /** Hard legibility limits. */
260
319
  declare const limits: {
261
- /** Mínimo absoluto en pantalla. */
320
+ /** Absolute minimum on screen. */
262
321
  readonly minScreenPx: 13;
263
- /** Mínimo absoluto impreso. */
322
+ /** Absolute minimum in print. */
264
323
  readonly minPrintPt: 12;
265
- /** Medida máxima de cuerpo. */
324
+ /** Maximum body measure. */
266
325
  readonly measure: "68ch";
267
326
  };
268
327
  declare const radius: {
@@ -273,43 +332,59 @@ declare const radius: {
273
332
  readonly pill: 999;
274
333
  };
275
334
  /**
276
- * Controles, del documento: `sm 8/14 · md 12/22 · lg 15/30 · icono 42×42`.
335
+ * Controls, from the document: `sm 8/14 · md 12/22 · lg 15/30 · icon 42×42`.
277
336
  *
278
- * Solo el padding horizontal y el cuadrado del botón de icono. El alto sale de
279
- * la escala tipográfica, y el radio es uno solo para los tres tamaños: ver
280
- * `docs/decisiones.md`.
337
+ * Only the horizontal padding and the icon button's square. Height comes from
338
+ * the type scale, and there is a single radius for all three sizes: see
339
+ * `docs/decisions.md`.
281
340
  *
282
- * No están en `spacing` porque no son ritmo de página: 14, 22 y 30 no componen
283
- * con 8/12/16/26/40 y no deben ofrecerse como márgenes.
341
+ * They are not in `spacing` because they are not page rhythm: 14, 22 and 30 do
342
+ * not compose with 8/12/16/26/40 and must not be offered as margins.
284
343
  */
285
344
  declare const control: {
286
345
  readonly sm: 14;
287
346
  readonly md: 22;
288
347
  readonly lg: 30;
289
- /** Botón de icono: cuadrado, sin texto. */
348
+ /** Icon button: square, no text. */
290
349
  readonly icon: 42;
350
+ /**
351
+ * The dense icon button, 32×32.
352
+ *
353
+ * 42 is the right measure for a control you hit with a thumb, and the four
354
+ * reading sites are where that fits. `cursos` is the odd one out: it is the
355
+ * only admin app of the set, with three actions per table row, and at 42 the
356
+ * row grows with them — the original used 24 and 28.
357
+ *
358
+ * It is 32 and not 28 because 32 is `sm`'s height. A dense icon button lines
359
+ * up with a small text button, so a toolbar mixing the two stays on one
360
+ * baseline; 28 would have been a fifth height that matches nothing.
361
+ *
362
+ * It does not replace `icon`. A page's primary action stays at 42; this is for
363
+ * a row of a table. See `docs/decisions.md` § 22.
364
+ */
365
+ readonly iconSm: 32;
291
366
  };
292
367
  /**
293
- * El ritmo de página. Los cinco escalones llevan `step` en el nombre, y no es
294
- * decoración: es la corrección de un bug que no dio la cara en ningún sitio.
368
+ * Page rhythm. All five steps carry `step` in the name, and that is not
369
+ * decoration: it is the fix for a bug that never surfaced anywhere.
295
370
  *
296
- * En Tailwind v4, `--spacing-*` no alimenta solo `p-*`, `m-*` y `gap-*`:
297
- * también resuelve `w-*`, `h-*`, `max-w-*`, `min-w-*`, `basis-*` y `size-*`, y
298
- * ahí GANA a la escala `--container-*`. Los escalones se llamaban `xs, sm, md,
299
- * lg, xl`, que son exactamente los nombres de esa escala, así que cualquier
300
- * proyecto que importara `theme.css` se quedaba con `max-w-sm` valiendo 12px en
301
- * vez de 384px. Nada avisaba: ni el build, ni los tipos, ni Storybook, ni la
302
- * suite —la librería no usa esas utilidades por dentro—. Se descubrió en
303
- * producción, con el párrafo de un hero a una palabra por línea.
371
+ * In Tailwind v4, `--spacing-*` does not only feed `p-*`, `m-*` and `gap-*`: it
372
+ * also resolves `w-*`, `h-*`, `max-w-*`, `min-w-*`, `basis-*` and `size-*`, and
373
+ * there it BEATS the `--container-*` scale. The steps used to be named `xs, sm,
374
+ * md, lg, xl`, which are exactly the names of that scale, so any project that
375
+ * imported `theme.css` ended up with `max-w-sm` worth 12px instead of 384px.
376
+ * Nothing warned: not the build, not the types, not Storybook, not the suite —
377
+ * the library does not use those utilities internally. It was found in
378
+ * production, with a hero paragraph running one word per line.
304
379
  *
305
- * Redeclarar `--container-sm` NO lo arregla: `--spacing-*` gana la resolución.
306
- * La única salida es que la librería no use esos nombres.
380
+ * Redeclaring `--container-sm` does NOT fix it: `--spacing-*` wins resolution.
381
+ * The only way out is for the library not to use those names.
307
382
  *
308
- * El prefijo sigue el patrón que ya tenía `control`: un grupo con nombre propio
309
- * dentro del espacio `--spacing-*`. `scripts/check-tokens-namespace.mjs` impide
310
- * la recaída.
383
+ * The prefix follows the pattern `control` already had: a named group inside
384
+ * the `--spacing-*` namespace. `scripts/check-tokens-namespace.mjs` prevents
385
+ * the relapse.
311
386
  *
312
- * `section` no lleva prefijo porque no choca con nada de Tailwind.
387
+ * `section` carries no prefix because it collides with nothing in Tailwind.
313
388
  */
314
389
  declare const spacing: {
315
390
  readonly stepXs: 8;
@@ -320,74 +395,100 @@ declare const spacing: {
320
395
  readonly section: 96;
321
396
  };
322
397
  declare const size: {
323
- /** Alto de la barra de navegación. */
398
+ /** Navigation bar height. */
324
399
  readonly nav: 64;
325
- /** Ancho de columna de lectura. */
400
+ /**
401
+ * The bar when it shares the screen with a sidebar.
402
+ *
403
+ * It is not «a smaller bar because it looks better». At 64 the header of an
404
+ * app shell competes with the rail beside it for the same corner, and the two
405
+ * together eat the top of the content area. 56 is what `cursos` had arrived at
406
+ * on its own, and it is the same reasoning as `control.iconSm`: the one admin
407
+ * app of the five is denser than the four reading sites. See
408
+ * `docs/decisions.md` § 30.
409
+ */
410
+ readonly navCompact: 56;
411
+ /**
412
+ * The admin sidebar, and the rail it collapses to.
413
+ *
414
+ * They are tokens and not the consumer's `w-*` because a collapsible sidebar
415
+ * has to know BOTH: the layout beside it reserves one of the two, and two
416
+ * numbers written by hand in two files drift the first time one of them moves.
417
+ * A sidebar that never collapses is still just a box the layout sizes.
418
+ *
419
+ * 56 is the rail: `navCompact`'s height, so a panel's bar and its rail meet in
420
+ * a square corner instead of a step.
421
+ */
422
+ readonly sidebar: 256;
423
+ readonly sidebarRail: 56;
424
+ /** Reading column width. */
326
425
  readonly content: 760;
327
- /** Ancho máximo de página. */
426
+ /** Maximum page width. */
328
427
  readonly wide: 1180;
329
428
  };
330
429
  /**
331
- * La paleta del resaltado de sintaxis.
430
+ * The syntax highlighting palette.
332
431
  *
333
- * Del documento, literal: «keywords arena, strings bioluz, comments plancton,
334
- * identifiers espuma», sobre casco. CUATRO colores a propósito — el sistema se
335
- * comunica con color y borde, no con ruido cromático, así que funciones,
336
- * variables y tipos caen todos en espuma.
432
+ * Straight from the document: «keywords sand, strings biolume, comments
433
+ * plankton, identifiers foam», over hull. FOUR colors on purpose — the system
434
+ * communicates with color and border, not with chromatic noise, so functions,
435
+ * variables and types all land on foam.
337
436
  *
338
- * El bloque de código es una isla de tema oscuro en los dos modos (ver
339
- * `CodeBlock`), así que esta paleta NO tiene par claro: siempre va sobre casco.
437
+ * The code block is an island of dark theme in both modes (see `CodeBlock`), so
438
+ * this palette has NO light counterpart: it always sits on hull.
340
439
  *
341
- * Contrastes MEDIDOS sobre `brand.hull` #0B1524, todos AA:
440
+ * Contrast MEASURED over `brand.hull` #0B1524, all AA:
342
441
  *
343
- * identificador espuma 16.42:1
344
- * literal bioluz 10.05:1
345
- * palabraClave arena 9.05:1
346
- * comentario plancton 5.43:1
347
- * invalido error 4.97:1
442
+ * identifier foam 16.42:1
443
+ * literal biolume 10.05:1
444
+ * keyword sand 9.05:1
445
+ * comment plankton 5.43:1
446
+ * invalid error 4.97:1
348
447
  *
349
- * `brand.body` (#3E7CB1) NO entra: el sistema lo restringe a relleno, nunca a
350
- * texto, y aquí mide 4.2:1.
448
+ * `brand.body` (#3E7CB1) is NOT here: the system restricts it to fill, never
449
+ * text, and it measures 4.2:1 in this context.
351
450
  *
352
- * Los literales numéricos y booleanos van con las cadenas en bioluz. El
353
- * documento no los asigna, y agruparlos con las cadenas —los tres son
354
- * literales— es más coherente que estrenar un quinto color fuera de la paleta.
451
+ * Numeric and boolean literals ride with strings in biolume. The document does
452
+ * not assign them, and grouping them with strings — all three are literals — is
453
+ * more coherent than introducing a fifth color outside the palette.
355
454
  */
356
- declare const sintaxis: {
357
- /** El casco. Es el fondo del bloque en los dos modos. */
358
- readonly fondo: "#0B1524";
359
- /** Identificadores, funciones, tipos, variables. */
360
- readonly identificador: "#EDF4F3";
361
- /** Cadenas, números, booleanos, null. */
455
+ declare const syntax: {
456
+ /** The hull. It is the block background in both modes. */
457
+ readonly background: "#0B1524";
458
+ /** Identifiers, functions, types, variables. */
459
+ readonly identifier: "#EDF4F3";
460
+ /** Strings, numbers, booleans, null. */
362
461
  readonly literal: "#35D6C0";
363
- /** Palabras clave, control de flujo, `import`, `this`. */
364
- readonly palabraClave: "#F2A65A";
365
- /** Comentarios y puntuación. */
366
- readonly comentario: "#71919C";
462
+ /** Keywords, control flow, `import`, `this`. */
463
+ readonly keyword: "#F2A65A";
464
+ /** Comments and punctuation. */
465
+ readonly comment: "#71919C";
367
466
  /** `markup.deleted`, `invalid`. */
368
- readonly invalido: "#E15757";
467
+ readonly invalid: "#E15757";
369
468
  };
370
469
  /**
371
- * La paleta de series de las gráficas. CUATRO, por el mismo motivo que la de
372
- * sintaxis: el sistema se comunica con color y borde, no con ruido cromático.
470
+ * The chart series palette. FOUR, for the same reason as the syntax palette:
471
+ * the system communicates with color and border, not with chromatic noise.
373
472
  *
374
- * Ninguno es un color nuevo. Son cuatro que ya están en la identidad y que se
375
- * distinguen por TONO, no por luminosidad —turquesa, naranja, azul y gris—,
376
- * que es la única forma de que sigan siendo cuatro series para quien no
377
- * distingue rojo y verde. Elegir bioluz y `success` habría dado dos verdes
378
- * casi idénticos en modo claro.
473
+ * None of them is a new color. They are four that already exist in the identity
474
+ * and that are told apart by HUE, not by lightness — teal, orange, blue and
475
+ * grey — which is the only way they stay four distinct series for someone who
476
+ * cannot tell socialLink from green. Picking biolume and `success` would have produced
477
+ * two nearly identical greens in light mode.
379
478
  *
380
- * `brand.body` entra aquí y no en el resaltado por la misma regla vista al
381
- * derecho: el sistema lo restringe a RELLENO y nunca a texto, y una serie de
382
- * gráfica es relleno. Es igual en los dos modos porque es color de marca.
479
+ * `brand.body` belongs here and not in syntax highlighting by the same rule
480
+ * read the right way round: the system restricts it to FILL and never to text,
481
+ * and a chart series is fill. It is identical in both modes because it is a
482
+ * brand color.
383
483
  *
384
- * El umbral que aplica es el de objeto gráfico, 3:1 contra el fondo, no el de
385
- * texto. Medidos contra `background`, los cuatro lo pasan en los dos modos con
386
- * margen: el peor es `brand.body` sobre papel, con 3.9:1.
484
+ * The threshold that applies is the graphical-object one, 3:1 against the
485
+ * background, not the text one. Measured against `background`, all four clear
486
+ * it in both modes with room to spare: the worst is `brand.body` over paper, at
487
+ * 3.9:1.
387
488
  *
388
- * Una quinta serie no se añade inventando un tono. Si una gráfica necesita
389
- * cinco categorías, o sobran categorías o hace falta agrupar en «otros»: ver
390
- * `docs/decisiones.md`.
489
+ * A fifth series is not added by inventing a hue. If a chart needs five
490
+ * categories, either there are too many categories or they need an «other»
491
+ * bucket: see `docs/decisions.md`.
391
492
  */
392
493
  declare const series: {
393
494
  readonly dark: readonly ["#35D6C0", "#F2A65A", "#3E7CB1", "#71919C"];
@@ -396,24 +497,24 @@ declare const series: {
396
497
  declare const gradient: {
397
498
  readonly dark: {
398
499
  readonly hero: "linear-gradient(160deg, #091319 60%, #0D2129 100%)";
399
- readonly seccion: "linear-gradient(150deg, #10202B 0%, #0D2129 100%)";
400
- /** El de la plantilla OG de artículo. 145°, del documento. */
500
+ readonly section: "linear-gradient(150deg, #10202B 0%, #0D2129 100%)";
501
+ /** The one used by the article OG template. 145°, from the document. */
401
502
  readonly og: "linear-gradient(145deg, #091319 55%, #0D2129 100%)";
402
503
  };
403
504
  readonly light: {
404
- readonly hero: "linear-gradient(160deg, #F6F2EA 60%, #EFE9DE 100%)";
405
- readonly seccion: "linear-gradient(150deg, #FFFFFF 0%, #EFE9DE 100%)";
406
- readonly og: "linear-gradient(145deg, #F6F2EA 55%, #EFE9DE 100%)";
505
+ readonly hero: "linear-gradient(160deg, #F6F2EA 60%, #FFFFFF 100%)";
506
+ readonly section: "linear-gradient(150deg, #FFFFFF 0%, #F6F2EA 100%)";
507
+ readonly og: "linear-gradient(145deg, #F6F2EA 55%, #FFFFFF 100%)";
407
508
  };
408
509
  };
409
- /** Un solo nivel. No hay escala de elevación. */
510
+ /** A single level. There is no elevation scale. */
410
511
  declare const shadow: {
411
512
  readonly standard: "0 1px 2px rgba(0, 0, 0, 0.35)";
412
513
  };
413
514
  /**
414
- * 150ms ease-out — solo color y borde.
415
- * El sistema no anima posición ni escala: los estados se comunican con borde
416
- * y color, no con movimiento.
515
+ * 150ms ease-out — color and border only.
516
+ * The system animates neither position nor scale: states are communicated with
517
+ * border and color, not with movement.
417
518
  */
418
519
  declare const motion: {
419
520
  readonly duration: "150ms";
@@ -422,20 +523,20 @@ declare const motion: {
422
523
  };
423
524
  declare const tagline: {
424
525
  /** Hero. */
425
- readonly largo: "Ayudo a equipos de ingeniería a escalar con criterio";
426
- /** Header, una línea. */
427
- readonly corto: "Ayudo a equipos a escalar con criterio";
526
+ readonly long: "Ayudo a equipos de ingeniería a escalar con criterio";
527
+ /** Header, one line. */
528
+ readonly short: "Ayudo a equipos a escalar con criterio";
428
529
  /** LinkedIn. */
429
530
  readonly en: "Helping engineering teams scale with judgment";
430
531
  };
431
532
  /**
432
- * El wordmark siempre dice «Eduardo Álvarez». La mascota se llama Tiburoncín
433
- * y nunca aparece escrita dentro del logo.
533
+ * The wordmark always reads «Eduardo Álvarez». The mascot is called Tiburoncín
534
+ * and its name never appears inside the logo.
434
535
  */
435
536
  declare const naming: {
436
537
  readonly wordmark: "Eduardo Álvarez";
437
538
  readonly mascot: "Tiburoncín";
438
- /** El dominio, para la firma CLI del footer: `$ cd ~/eduardoalvarez.dev/2026`. */
539
+ /** The domain, for the footer CLI signature: `$ cd ~/eduardoalvarez.dev/2026`. */
439
540
  readonly domain: "eduardoalvarez.dev";
440
541
  };
441
542
  type ColorMode = keyof typeof colors;
@@ -446,20 +547,21 @@ type TypeScaleToken = keyof typeof typeScale;
446
547
  type RadiusToken = keyof typeof radius;
447
548
  type ControlToken = keyof typeof control;
448
549
  type GradientToken = keyof typeof gradient.dark;
449
- type SintaxisToken = keyof typeof sintaxis;
550
+ type SyntaxToken = keyof typeof syntax;
450
551
  type SpacingToken = keyof typeof spacing;
451
552
  type SizeToken = keyof typeof size;
452
- /** El índice de una serie de gráfica: 0, 1, 2 o 3. */
553
+ /** The index of a chart series: 0, 1, 2 or 3. */
453
554
  type SeriesToken = 0 | 1 | 2 | 3;
454
555
 
455
556
  /**
456
- * Punto de entrada de `@eduardoalvarez/arrecife/tokens`.
557
+ * The entry point of `@eduardoalvarez/arrecife/tokens`.
457
558
  *
458
- * Igual que `tokens.ts`: no importa nada fuera de este directorio. Es el único
459
- * subpaquete que pueden consumir los cinco proyectos, Satori y Astro sin React.
559
+ * Same as `tokens.ts`: it imports nothing from outside this directory. It is the
560
+ * only subpackage the five projects, Satori and React-less Astro can all
561
+ * consume.
460
562
  */
461
563
 
462
- /** Todos los tokens en un solo objeto, para plantillas Satori y generadores. */
564
+ /** Every token in a single object, for Satori templates and generators. */
463
565
  declare const tokens: {
464
566
  readonly colors: {
465
567
  readonly dark: {
@@ -481,6 +583,9 @@ declare const tokens: {
481
583
  readonly success: "#4FB477";
482
584
  readonly warning: "#E8A33D";
483
585
  readonly error: "#E15757";
586
+ readonly danger: "#F4736B";
587
+ readonly dangerHover: "#F78D86";
588
+ readonly dangerOn: "#2B0A08";
484
589
  };
485
590
  readonly light: {
486
591
  readonly background: "#F6F2EA";
@@ -501,6 +606,9 @@ declare const tokens: {
501
606
  readonly success: "#0F6B52";
502
607
  readonly warning: "#8D6111";
503
608
  readonly error: "#C0392B";
609
+ readonly danger: "#C0392B";
610
+ readonly dangerHover: "#A32F22";
611
+ readonly dangerOn: "#FFF6F4";
504
612
  };
505
613
  };
506
614
  readonly brand: {
@@ -615,6 +723,7 @@ declare const tokens: {
615
723
  readonly md: 22;
616
724
  readonly lg: 30;
617
725
  readonly icon: 42;
726
+ readonly iconSm: 32;
618
727
  };
619
728
  readonly spacing: {
620
729
  readonly stepXs: 8;
@@ -626,28 +735,31 @@ declare const tokens: {
626
735
  };
627
736
  readonly size: {
628
737
  readonly nav: 64;
738
+ readonly navCompact: 56;
739
+ readonly sidebar: 256;
740
+ readonly sidebarRail: 56;
629
741
  readonly content: 760;
630
742
  readonly wide: 1180;
631
743
  };
632
744
  readonly gradient: {
633
745
  readonly dark: {
634
746
  readonly hero: "linear-gradient(160deg, #091319 60%, #0D2129 100%)";
635
- readonly seccion: "linear-gradient(150deg, #10202B 0%, #0D2129 100%)";
747
+ readonly section: "linear-gradient(150deg, #10202B 0%, #0D2129 100%)";
636
748
  readonly og: "linear-gradient(145deg, #091319 55%, #0D2129 100%)";
637
749
  };
638
750
  readonly light: {
639
- readonly hero: "linear-gradient(160deg, #F6F2EA 60%, #EFE9DE 100%)";
640
- readonly seccion: "linear-gradient(150deg, #FFFFFF 0%, #EFE9DE 100%)";
641
- readonly og: "linear-gradient(145deg, #F6F2EA 55%, #EFE9DE 100%)";
751
+ readonly hero: "linear-gradient(160deg, #F6F2EA 60%, #FFFFFF 100%)";
752
+ readonly section: "linear-gradient(150deg, #FFFFFF 0%, #F6F2EA 100%)";
753
+ readonly og: "linear-gradient(145deg, #F6F2EA 55%, #FFFFFF 100%)";
642
754
  };
643
755
  };
644
- readonly sintaxis: {
645
- readonly fondo: "#0B1524";
646
- readonly identificador: "#EDF4F3";
756
+ readonly syntax: {
757
+ readonly background: "#0B1524";
758
+ readonly identifier: "#EDF4F3";
647
759
  readonly literal: "#35D6C0";
648
- readonly palabraClave: "#F2A65A";
649
- readonly comentario: "#71919C";
650
- readonly invalido: "#E15757";
760
+ readonly keyword: "#F2A65A";
761
+ readonly comment: "#71919C";
762
+ readonly invalid: "#E15757";
651
763
  };
652
764
  readonly series: {
653
765
  readonly dark: readonly ["#35D6C0", "#F2A65A", "#3E7CB1", "#71919C"];
@@ -662,8 +774,8 @@ declare const tokens: {
662
774
  readonly properties: "color, background-color, border-color, fill, stroke";
663
775
  };
664
776
  readonly tagline: {
665
- readonly largo: "Ayudo a equipos de ingeniería a escalar con criterio";
666
- readonly corto: "Ayudo a equipos a escalar con criterio";
777
+ readonly long: "Ayudo a equipos de ingeniería a escalar con criterio";
778
+ readonly short: "Ayudo a equipos a escalar con criterio";
667
779
  readonly en: "Helping engineering teams scale with judgment";
668
780
  };
669
781
  readonly naming: {
@@ -674,4 +786,4 @@ declare const tokens: {
674
786
  };
675
787
  type Tokens = typeof tokens;
676
788
 
677
- export { type BrandToken, type ColorMode, type ColorToken, type ControlToken, type FontToken, type GradientToken, type RadiusToken, type SeriesToken, type SintaxisToken, type SizeToken, type SpacingToken, type Tokens, type TypeScaleToken, brand, colors, control, dark, fonts, gradient, light, limits, motion, naming, radius, series, shadow, sintaxis, size, spacing, tagline, tokens, typeScale };
789
+ export { type BrandToken, type ColorMode, type ColorToken, type ControlToken, type FontToken, type GradientToken, type RadiusToken, type SeriesToken, type SizeToken, type SpacingToken, type SyntaxToken, type Tokens, type TypeScaleToken, brand, colors, control, dark, fonts, gradient, light, limits, motion, naming, radius, series, shadow, size, spacing, syntax, tagline, tokens, typeScale };