@eduardoalvarez/arrecife 0.10.0 → 0.12.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 (42) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/README.md +44 -13
  3. package/dist/brand/index.cjs +11 -5
  4. package/dist/brand/index.d.cts +45 -6
  5. package/dist/brand/index.d.ts +45 -6
  6. package/dist/brand/index.js +3 -3
  7. package/dist/chart/index.cjs +28 -6
  8. package/dist/chart/index.d.cts +21 -5
  9. package/dist/chart/index.d.ts +21 -5
  10. package/dist/chart/index.js +29 -7
  11. package/dist/{chunk-FGFNK72B.js → chunk-5YWGOFDX.js} +17 -4
  12. package/dist/{chunk-5A5GH2PF.js → chunk-6QJQ6K7J.js} +1 -1
  13. package/dist/{chunk-TRPBID2W.js → chunk-BFYNBIVJ.js} +1 -1
  14. package/dist/{chunk-IIT3YLYN.js → chunk-BRDTB44R.js} +12 -6
  15. package/dist/{chunk-XXDATT3A.js → chunk-FF33ARRA.js} +1 -1
  16. package/dist/{chunk-FAAGZG7A.js → chunk-TMUGT3Y3.js} +1 -1
  17. package/dist/{chunk-6IGD5REB.js → chunk-W75O3Z77.js} +1 -1
  18. package/dist/{chunk-ZSCSKCTY.js → chunk-WU66TPJT.js} +1 -1
  19. package/dist/form/index.cjs +2 -2
  20. package/dist/form/index.js +4 -4
  21. package/dist/icons/index.cjs +2 -2
  22. package/dist/icons/index.d.cts +2 -2
  23. package/dist/icons/index.d.ts +2 -2
  24. package/dist/icons/index.js +3 -3
  25. package/dist/index.cjs +153 -31
  26. package/dist/index.d.cts +95 -18
  27. package/dist/index.d.ts +95 -18
  28. package/dist/index.js +141 -38
  29. package/dist/og/index.cjs +1 -2
  30. package/dist/og/index.js +1 -1
  31. package/dist/shiki/index.js +1 -1
  32. package/dist/tokens/index.cjs +17 -4
  33. package/dist/tokens/index.d.cts +20 -5
  34. package/dist/tokens/index.d.ts +20 -5
  35. package/dist/tokens/index.js +2 -2
  36. package/dist/tokens/theme.css +20 -3
  37. package/dist/variants/index.cjs +1 -1
  38. package/dist/variants/index.d.cts +2 -2
  39. package/dist/variants/index.d.ts +2 -2
  40. package/dist/variants/index.js +1 -1
  41. package/llms.txt +71 -13
  42. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,23 +1,23 @@
1
1
  'use client';
2
- import { Label } from './chunk-6IGD5REB.js';
3
- export { Label } from './chunk-6IGD5REB.js';
4
- import { Text } from './chunk-TRPBID2W.js';
5
- export { Text } from './chunk-TRPBID2W.js';
6
- export { tokens } from './chunk-5A5GH2PF.js';
2
+ import { Label } from './chunk-W75O3Z77.js';
3
+ export { Label } from './chunk-W75O3Z77.js';
4
+ import { Text } from './chunk-BFYNBIVJ.js';
5
+ export { Text } from './chunk-BFYNBIVJ.js';
6
+ export { tokens } from './chunk-6QJQ6K7J.js';
7
7
  import { toggleTheme, currentTheme, watchTheme } from './chunk-GCRII2KQ.js';
8
8
  export { THEME_ATTRIBUTE, THEME_EVENT, THEME_KEY, applyTheme, currentTheme, preferredTheme, storedTheme, themeScript, toggleTheme, watchTheme } from './chunk-GCRII2KQ.js';
9
- import { alert, button, avatar, badge, category, metric, CARD_SURFACE, CARD } from './chunk-XXDATT3A.js';
10
- export { CARD, CARD_HOVER, CARD_SURFACE, alert as alertVariants, avatar as avatarVariants, badge as badgeVariants, button as buttonVariants, category as categoryBadgeVariants, metric as metricBadgeVariants } from './chunk-XXDATT3A.js';
9
+ import { alert, button, avatar, badge, category, metric, CARD_SURFACE, CARD } from './chunk-FF33ARRA.js';
10
+ export { CARD, CARD_HOVER, CARD_SURFACE, alert as alertVariants, avatar as avatarVariants, badge as badgeVariants, button as buttonVariants, category as categoryBadgeVariants, metric as metricBadgeVariants } from './chunk-FF33ARRA.js';
11
11
  export { text as textVariants } from './chunk-ODBFN44D.js';
12
- import { MascotFace, Mascot } from './chunk-IIT3YLYN.js';
13
- export { Isotype, Logo, Mascot, MascotFace } from './chunk-IIT3YLYN.js';
14
- import { Icon } from './chunk-ZSCSKCTY.js';
15
- import { cn } from './chunk-FAAGZG7A.js';
16
- export { cn } from './chunk-FAAGZG7A.js';
12
+ import { MascotFace, Mascot } from './chunk-BRDTB44R.js';
13
+ export { Isotype, Logo, Mascot, MascotFace } from './chunk-BRDTB44R.js';
14
+ import { Icon } from './chunk-WU66TPJT.js';
15
+ import { cn } from './chunk-TMUGT3Y3.js';
16
+ export { cn } from './chunk-TMUGT3Y3.js';
17
17
  export { ASSETS_PATH, faceList, faceUsage, faces, fins, poseList, poses } from './chunk-CKRSQPTX.js';
18
- import { naming } from './chunk-FGFNK72B.js';
19
- export { brand, colors, control, dark, fonts, gradient, light, limits, motion, naming, radius, series, shadow, size, spacing, syntax, tagline, typeScale } from './chunk-FGFNK72B.js';
20
- import { CaretDown, XCircle, Warning, CheckCircle, Info, Camera, CircleNotch, CaretLeft, CaretRight, Minus, Check, X, DotsThree, CaretUp, Copy, ArrowUpRight, TrendDown, TrendUp, Sun, Moon, WarningCircle, Waveform, ArrowCounterClockwise, ArrowClockwise, SpeakerSlash, SpeakerHigh, ArrowsClockwise, Pause, Play } from '@phosphor-icons/react';
18
+ import { naming } from './chunk-5YWGOFDX.js';
19
+ export { brand, colors, control, dark, fonts, gradient, light, limits, motion, naming, radius, series, shadow, size, spacing, syntax, tagline, typeScale } from './chunk-5YWGOFDX.js';
20
+ import { CaretDown, XCircle, Warning, CheckCircle, Info, Camera, CircleNotch, CaretLeft, CaretRight, Minus, Check, X, DotsThree, CaretUp, Copy, ArrowUpRight, TrendDown, TrendUp, Sun, Moon, WarningCircle, Waveform, ArrowCounterClockwise, ArrowClockwise, SpeakerSlash, SpeakerHigh, ArrowsClockwise, Pause, Play, Heart } from '@phosphor-icons/react';
21
21
  import * as AccordionPrimitive from '@radix-ui/react-accordion';
22
22
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
23
23
  import { cva } from 'class-variance-authority';
@@ -2181,25 +2181,62 @@ function CourseCard({
2181
2181
  meta,
2182
2182
  status,
2183
2183
  progress,
2184
+ media,
2185
+ footer,
2184
2186
  className,
2185
2187
  ...props
2186
2188
  }) {
2187
- return /* @__PURE__ */ jsx(CardShell, { className: cn("p-step-lg", className), ...props, children: /* @__PURE__ */ jsxs("article", { className: "gap-step-sm flex h-full flex-col", children: [
2188
- status ? /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Badge, { variant: "warm", children: status }) }) : null,
2189
- /* @__PURE__ */ jsx(Text, { as: "h3", variant: "h3", className: "group-hover:text-accent transition-standard", children: title }),
2190
- summary ? /* @__PURE__ */ jsx(Text, { variant: "ui", tone: "secondary", className: "line-clamp-3", children: summary }) : null,
2191
- meta && meta.length > 0 ? /* @__PURE__ */ jsx(Text, { variant: "label", tone: "muted", as: "p", className: "gap-step-xs flex flex-wrap items-center", children: meta.map((m, i) => /* @__PURE__ */ jsxs("span", { className: "gap-step-xs flex items-center", children: [
2192
- i > 0 ? /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\xB7" }) : null,
2193
- m
2194
- ] }, i)) }) : null,
2195
- typeof progress === "number" ? /* @__PURE__ */ jsxs("div", { className: "gap-step-xs mt-auto flex flex-col pt-step-sm", children: [
2196
- /* @__PURE__ */ jsx(Progress, { value: progress, tone: "warm", label: `Progreso del curso: ${progress}%` }),
2197
- /* @__PURE__ */ jsxs(Text, { variant: "label", tone: "muted", as: "p", children: [
2198
- progress,
2199
- "% cursado"
2200
- ] })
2201
- ] }) : null
2202
- ] }) });
2189
+ const hasProgress = typeof progress === "number";
2190
+ return (
2191
+ // `overflow-hidden` only with a cover: it is what rounds the cover's top
2192
+ // corners to the card's. It clips the content and not the `<a>` itself, so
2193
+ // the focus ring — an outline three pixels outside — still shows.
2194
+ /* @__PURE__ */ jsx(
2195
+ CardShell,
2196
+ {
2197
+ className: cn("p-step-lg", media ? "overflow-hidden" : null, className),
2198
+ ...props,
2199
+ children: /* @__PURE__ */ jsxs("article", { className: "gap-step-sm flex h-full flex-col", children: [
2200
+ media ? (
2201
+ // The bleed is the card's own padding, negated. A call site that
2202
+ // changes the padding through `className` has to change this too, and
2203
+ // that is the trade for keeping the padding on the shell like every
2204
+ // other card instead of in a second place only when there is a cover.
2205
+ /* @__PURE__ */ jsx("div", { className: "-mx-step-lg -mt-step-lg mb-step-xs", children: media })
2206
+ ) : null,
2207
+ status ? /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Badge, { variant: "warm", children: status }) }) : null,
2208
+ /* @__PURE__ */ jsx(Text, { as: "h3", variant: "h3", className: "group-hover:text-accent transition-standard", children: title }),
2209
+ summary ? /* @__PURE__ */ jsx(Text, { variant: "ui", tone: "secondary", className: "line-clamp-3", children: summary }) : null,
2210
+ meta && meta.length > 0 ? /* @__PURE__ */ jsx(Text, { variant: "label", tone: "muted", as: "p", className: "gap-step-xs flex flex-wrap items-center", children: meta.map((m, i) => /* @__PURE__ */ jsxs("span", { className: "gap-step-xs flex items-center", children: [
2211
+ i > 0 ? /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\xB7" }) : null,
2212
+ m
2213
+ ] }, i)) }) : null,
2214
+ hasProgress ? /* @__PURE__ */ jsxs("div", { className: "gap-step-xs mt-auto flex flex-col pt-step-sm", children: [
2215
+ /* @__PURE__ */ jsx(Progress, { value: progress, tone: "warm", label: `Progreso del curso: ${progress}%` }),
2216
+ /* @__PURE__ */ jsxs(Text, { variant: "label", tone: "muted", as: "p", children: [
2217
+ progress,
2218
+ "% cursado"
2219
+ ] })
2220
+ ] }) : null,
2221
+ footer ? (
2222
+ // Only one of the two takes `mt-auto`. Two auto margins in one column
2223
+ // split the free space between them, and the progress bar would float
2224
+ // halfway down the card.
2225
+ /* @__PURE__ */ jsx(
2226
+ "div",
2227
+ {
2228
+ className: cn(
2229
+ "gap-step-sm pt-step-sm flex flex-wrap items-center justify-between",
2230
+ hasProgress ? null : "mt-auto"
2231
+ ),
2232
+ children: footer
2233
+ }
2234
+ )
2235
+ ) : null
2236
+ ] })
2237
+ }
2238
+ )
2239
+ );
2203
2240
  }
2204
2241
  var FACE = "w-[66px] max-w-none";
2205
2242
  function EmptyState(props) {
@@ -2441,8 +2478,7 @@ function SocialRow({ social }) {
2441
2478
  function Signature({
2442
2479
  year,
2443
2480
  href,
2444
- domain: domainName = naming.domain,
2445
- className
2481
+ domain: domainName = naming.domain
2446
2482
  }) {
2447
2483
  const domain = href ? /* @__PURE__ */ jsx(
2448
2484
  "a",
@@ -2452,7 +2488,7 @@ function Signature({
2452
2488
  children: domainName
2453
2489
  }
2454
2490
  ) : domainName;
2455
- return /* @__PURE__ */ jsxs(Text, { variant: "meta", tone: "muted", as: "p", className: cn("shrink-0", className), children: [
2491
+ return /* @__PURE__ */ jsxs(Text, { variant: "meta", tone: "muted", as: "p", children: [
2456
2492
  /* @__PURE__ */ jsxs("span", { "aria-hidden": "true", className: "text-accent", children: [
2457
2493
  "$",
2458
2494
  " "
@@ -2470,6 +2506,46 @@ function Signature({
2470
2506
  )
2471
2507
  ] });
2472
2508
  }
2509
+ function BuiltWith() {
2510
+ return /* @__PURE__ */ jsxs(Text, { variant: "meta", tone: "muted", as: "p", children: [
2511
+ "Creado con",
2512
+ " ",
2513
+ /* @__PURE__ */ jsx(
2514
+ "a",
2515
+ {
2516
+ href: naming.libraryUrl,
2517
+ target: "_blank",
2518
+ rel: "noopener noreferrer",
2519
+ className: cn(
2520
+ "text-accent hover:text-text-primary transition-standard cursor-pointer",
2521
+ "underline decoration-1 underline-offset-4",
2522
+ "rounded-chip focus-ring"
2523
+ ),
2524
+ children: naming.library
2525
+ }
2526
+ ),
2527
+ " ",
2528
+ /* @__PURE__ */ jsx(Icon, { as: Heart, tone: "current", className: "text-accent inline align-middle" })
2529
+ ] });
2530
+ }
2531
+ function SignatureBlock({
2532
+ year,
2533
+ href,
2534
+ domain,
2535
+ builtWith,
2536
+ className
2537
+ }) {
2538
+ return /* @__PURE__ */ jsxs(
2539
+ "div",
2540
+ {
2541
+ className: cn("gap-step-xs flex shrink-0 flex-col items-center sm:items-end", className),
2542
+ children: [
2543
+ /* @__PURE__ */ jsx(Signature, { year, href, domain }),
2544
+ builtWith ? /* @__PURE__ */ jsx(BuiltWith, {}) : null
2545
+ ]
2546
+ }
2547
+ );
2548
+ }
2473
2549
  function Shell({
2474
2550
  className,
2475
2551
  contentClassName,
@@ -2492,6 +2568,7 @@ function Footer({
2492
2568
  linkAsChild,
2493
2569
  social,
2494
2570
  brand: brand2,
2571
+ builtWith,
2495
2572
  year = (/* @__PURE__ */ new Date()).getFullYear(),
2496
2573
  signatureHref,
2497
2574
  domain,
@@ -2541,7 +2618,15 @@ function Footer({
2541
2618
  column.title
2542
2619
  )) })
2543
2620
  ] }),
2544
- /* @__PURE__ */ jsx("div", { className: "border-hairline mt-step-xl pt-step-lg border-t", children: /* @__PURE__ */ jsx(Signature, { year, href: signatureHref, domain, className: "text-center sm:text-right" }) })
2621
+ /* @__PURE__ */ jsx("div", { className: "border-hairline mt-step-xl pt-step-lg border-t", children: /* @__PURE__ */ jsx(
2622
+ SignatureBlock,
2623
+ {
2624
+ year,
2625
+ href: signatureHref,
2626
+ domain,
2627
+ builtWith
2628
+ }
2629
+ ) })
2545
2630
  ] });
2546
2631
  }
2547
2632
  const rows = [
@@ -2552,7 +2637,16 @@ function Footer({
2552
2637
  return /* @__PURE__ */ jsxs(Shell, { className, contentClassName: "gap-step-lg", ...rest, children: [
2553
2638
  /* @__PURE__ */ jsxs("div", { className: "gap-step-md flex flex-col items-center sm:flex-row sm:flex-wrap", children: [
2554
2639
  first ?? null,
2555
- /* @__PURE__ */ jsx(Signature, { year, href: signatureHref, domain, className: "sm:ml-auto" })
2640
+ /* @__PURE__ */ jsx(
2641
+ SignatureBlock,
2642
+ {
2643
+ year,
2644
+ href: signatureHref,
2645
+ domain,
2646
+ builtWith,
2647
+ className: "sm:ml-auto"
2648
+ }
2649
+ )
2556
2650
  ] }),
2557
2651
  others
2558
2652
  ] });
@@ -2703,7 +2797,7 @@ function Nav({ brand: brand2, children, actions, size: size2 = "default", classN
2703
2797
  puts it in `actions`. A `Nav` that hid its own items would leave every
2704
2798
  consumer without a drawer with no navigation at all, silently.
2705
2799
 
2706
- See `docs/decisions/0.10.md` § 54.
2800
+ See `docs/decisions/` § 54.
2707
2801
  */
2708
2802
  /* @__PURE__ */ jsx("nav", { "aria-label": "Principal", className: "ml-auto min-w-0 overflow-x-auto", children: /* @__PURE__ */ jsxs("ul", { className: "gap-step-md flex w-max items-center", children: [
2709
2803
  /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "text-text-muted font-mono text-meta select-none", children: "~/" }),
@@ -2881,12 +2975,21 @@ function PageHeader({
2881
2975
  action,
2882
2976
  size: size2,
2883
2977
  as = "h1",
2978
+ titleVariant,
2884
2979
  className,
2885
2980
  ...props
2886
2981
  }) {
2887
2982
  return /* @__PURE__ */ jsxs("header", { className: cn(header({ size: size2 }), className), ...props, children: [
2888
2983
  eyebrow ? /* @__PURE__ */ jsx(Text, { variant: "eyebrow", tone: "accent", as: "p", children: eyebrow }) : null,
2889
- /* @__PURE__ */ jsx(Text, { as, variant: size2 === "display" ? "display" : "h1", className: "max-w-measure", children: title }),
2984
+ /* @__PURE__ */ jsx(
2985
+ Text,
2986
+ {
2987
+ as,
2988
+ variant: titleVariant ?? (size2 === "display" ? "display" : "h1"),
2989
+ className: "max-w-measure",
2990
+ children: title
2991
+ }
2992
+ ),
2890
2993
  description ? /* @__PURE__ */ jsx(Text, { variant: "body", tone: "secondary", children: description }) : null,
2891
2994
  action ? /* @__PURE__ */ jsx("div", { className: "gap-step-sm mt-step-sm flex flex-wrap items-center", children: action }) : null
2892
2995
  ] });
package/dist/og/index.cjs CHANGED
@@ -74,8 +74,7 @@ var tagline = {
74
74
  var naming = {
75
75
  wordmark: "Eduardo \xC1lvarez",
76
76
  /** The domain, for the footer CLI signature: `$ cd ~/eduardoalvarez.dev/2026`. */
77
- domain: "eduardoalvarez.dev"
78
- };
77
+ domain: "eduardoalvarez.dev"};
79
78
 
80
79
  // src/og/templates.ts
81
80
  var OG = {
package/dist/og/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ASSETS_PATH, faces, poses, fins } from '../chunk-CKRSQPTX.js';
2
- import { fonts, dark, light, naming, gradient, tagline, typeScale } from '../chunk-FGFNK72B.js';
2
+ import { fonts, dark, light, naming, gradient, tagline, typeScale } from '../chunk-5YWGOFDX.js';
3
3
 
4
4
  // src/og/templates.ts
5
5
  var OG = {
@@ -1,4 +1,4 @@
1
- import { syntax } from '../chunk-FGFNK72B.js';
1
+ import { syntax } from '../chunk-5YWGOFDX.js';
2
2
 
3
3
  // src/shiki/theme.ts
4
4
  var arrecife = {
@@ -146,7 +146,7 @@ var typeScale = {
146
146
  * (plankton 5.57:1 over abyss), which is the part that is not negotiable.
147
147
  *
148
148
  * At 13 the three badge families grew past the size of a small button and
149
- * outweighed the title they accompany. See `docs/decisions/`.
149
+ * outweighed the title they accompany. See `docs/decisions/` § 10.
150
150
  */
151
151
  chip: { family: "mono", size: 11.5, lineHeight: 1.4, weight: 400 },
152
152
  /**
@@ -200,7 +200,7 @@ var control = {
200
200
  * baseline; 28 would have been a fifth height that matches nothing.
201
201
  *
202
202
  * It does not replace `icon`. A page's primary action stays at 42; this is for
203
- * a row of a table. See `docs/decisions/0.6.md` § 22.
203
+ * a row of a table. See `docs/decisions/` § 22.
204
204
  */
205
205
  iconSm: 32
206
206
  };
@@ -223,7 +223,7 @@ var size = {
223
223
  * together eat the top of the content area. 56 is what `cursos` had arrived at
224
224
  * on its own, and it is the same reasoning as `control.iconSm`: the one admin
225
225
  * app of the five is denser than the four reading sites. See
226
- * `docs/decisions/0.7.md` § 30.
226
+ * `docs/decisions/` § 30.
227
227
  */
228
228
  navCompact: 56,
229
229
  /**
@@ -296,7 +296,20 @@ var naming = {
296
296
  wordmark: "Eduardo \xC1lvarez",
297
297
  mascot: "Tiburonc\xEDn",
298
298
  /** The domain, for the footer CLI signature: `$ cd ~/eduardoalvarez.dev/2026`. */
299
- domain: "eduardoalvarez.dev"
299
+ domain: "eduardoalvarez.dev",
300
+ /** The library's own name, for a footer that credits it. */
301
+ library: "Arrecife",
302
+ /**
303
+ * Where the library is published, for `Footer builtWith`.
304
+ *
305
+ * It is here and not written into the component for the reason the domain is:
306
+ * one string, five projects. It is the same URL as `homepage` in
307
+ * `package.json` and it cannot be derived from it — this file imports nothing
308
+ * — so `check:exports` compares the two on every build. Without that, moving
309
+ * the Storybook would update what npm prints and leave five production
310
+ * footers linking at the old address.
311
+ */
312
+ libraryUrl: "https://arrecife.eduardoalvarez.dev"
300
313
  };
301
314
 
302
315
  // src/tokens/index.ts
@@ -280,7 +280,7 @@ declare const typeScale: {
280
280
  * (plankton 5.57:1 over abyss), which is the part that is not negotiable.
281
281
  *
282
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/`.
283
+ * outweighed the title they accompany. See `docs/decisions/` § 10.
284
284
  */
285
285
  readonly chip: {
286
286
  readonly family: "mono";
@@ -336,7 +336,7 @@ declare const radius: {
336
336
  *
337
337
  * Only the horizontal padding and the icon button's square. Height comes from
338
338
  * the type scale, and there is a single radius for all three sizes: see
339
- * `docs/decisions/`.
339
+ * `docs/decisions/` § 1.
340
340
  *
341
341
  * They are not in `spacing` because they are not page rhythm: 14, 22 and 30 do
342
342
  * not compose with 8/12/16/26/40 and must not be offered as margins.
@@ -360,7 +360,7 @@ declare const control: {
360
360
  * baseline; 28 would have been a fifth height that matches nothing.
361
361
  *
362
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/0.6.md` § 22.
363
+ * a row of a table. See `docs/decisions/` § 22.
364
364
  */
365
365
  readonly iconSm: 32;
366
366
  };
@@ -405,7 +405,7 @@ declare const size: {
405
405
  * together eat the top of the content area. 56 is what `cursos` had arrived at
406
406
  * on its own, and it is the same reasoning as `control.iconSm`: the one admin
407
407
  * app of the five is denser than the four reading sites. See
408
- * `docs/decisions/0.7.md` § 30.
408
+ * `docs/decisions/` § 30.
409
409
  */
410
410
  readonly navCompact: 56;
411
411
  /**
@@ -488,7 +488,7 @@ declare const syntax: {
488
488
  *
489
489
  * A fifth series is not added by inventing a hue. If a chart needs five
490
490
  * categories, either there are too many categories or they need an «other»
491
- * bucket: see `docs/decisions/`.
491
+ * bucket: see `docs/decisions/` § 18.
492
492
  */
493
493
  declare const series: {
494
494
  readonly dark: readonly ["#35D6C0", "#F2A65A", "#3E7CB1", "#71919C"];
@@ -538,6 +538,19 @@ declare const naming: {
538
538
  readonly mascot: "Tiburoncín";
539
539
  /** The domain, for the footer CLI signature: `$ cd ~/eduardoalvarez.dev/2026`. */
540
540
  readonly domain: "eduardoalvarez.dev";
541
+ /** The library's own name, for a footer that credits it. */
542
+ readonly library: "Arrecife";
543
+ /**
544
+ * Where the library is published, for `Footer builtWith`.
545
+ *
546
+ * It is here and not written into the component for the reason the domain is:
547
+ * one string, five projects. It is the same URL as `homepage` in
548
+ * `package.json` and it cannot be derived from it — this file imports nothing
549
+ * — so `check:exports` compares the two on every build. Without that, moving
550
+ * the Storybook would update what npm prints and leave five production
551
+ * footers linking at the old address.
552
+ */
553
+ readonly libraryUrl: "https://arrecife.eduardoalvarez.dev";
541
554
  };
542
555
  type ColorMode = keyof typeof colors;
543
556
  type ColorToken = keyof typeof dark;
@@ -782,6 +795,8 @@ declare const tokens: {
782
795
  readonly wordmark: "Eduardo Álvarez";
783
796
  readonly mascot: "Tiburoncín";
784
797
  readonly domain: "eduardoalvarez.dev";
798
+ readonly library: "Arrecife";
799
+ readonly libraryUrl: "https://arrecife.eduardoalvarez.dev";
785
800
  };
786
801
  };
787
802
  type Tokens = typeof tokens;
@@ -280,7 +280,7 @@ declare const typeScale: {
280
280
  * (plankton 5.57:1 over abyss), which is the part that is not negotiable.
281
281
  *
282
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/`.
283
+ * outweighed the title they accompany. See `docs/decisions/` § 10.
284
284
  */
285
285
  readonly chip: {
286
286
  readonly family: "mono";
@@ -336,7 +336,7 @@ declare const radius: {
336
336
  *
337
337
  * Only the horizontal padding and the icon button's square. Height comes from
338
338
  * the type scale, and there is a single radius for all three sizes: see
339
- * `docs/decisions/`.
339
+ * `docs/decisions/` § 1.
340
340
  *
341
341
  * They are not in `spacing` because they are not page rhythm: 14, 22 and 30 do
342
342
  * not compose with 8/12/16/26/40 and must not be offered as margins.
@@ -360,7 +360,7 @@ declare const control: {
360
360
  * baseline; 28 would have been a fifth height that matches nothing.
361
361
  *
362
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/0.6.md` § 22.
363
+ * a row of a table. See `docs/decisions/` § 22.
364
364
  */
365
365
  readonly iconSm: 32;
366
366
  };
@@ -405,7 +405,7 @@ declare const size: {
405
405
  * together eat the top of the content area. 56 is what `cursos` had arrived at
406
406
  * on its own, and it is the same reasoning as `control.iconSm`: the one admin
407
407
  * app of the five is denser than the four reading sites. See
408
- * `docs/decisions/0.7.md` § 30.
408
+ * `docs/decisions/` § 30.
409
409
  */
410
410
  readonly navCompact: 56;
411
411
  /**
@@ -488,7 +488,7 @@ declare const syntax: {
488
488
  *
489
489
  * A fifth series is not added by inventing a hue. If a chart needs five
490
490
  * categories, either there are too many categories or they need an «other»
491
- * bucket: see `docs/decisions/`.
491
+ * bucket: see `docs/decisions/` § 18.
492
492
  */
493
493
  declare const series: {
494
494
  readonly dark: readonly ["#35D6C0", "#F2A65A", "#3E7CB1", "#71919C"];
@@ -538,6 +538,19 @@ declare const naming: {
538
538
  readonly mascot: "Tiburoncín";
539
539
  /** The domain, for the footer CLI signature: `$ cd ~/eduardoalvarez.dev/2026`. */
540
540
  readonly domain: "eduardoalvarez.dev";
541
+ /** The library's own name, for a footer that credits it. */
542
+ readonly library: "Arrecife";
543
+ /**
544
+ * Where the library is published, for `Footer builtWith`.
545
+ *
546
+ * It is here and not written into the component for the reason the domain is:
547
+ * one string, five projects. It is the same URL as `homepage` in
548
+ * `package.json` and it cannot be derived from it — this file imports nothing
549
+ * — so `check:exports` compares the two on every build. Without that, moving
550
+ * the Storybook would update what npm prints and leave five production
551
+ * footers linking at the old address.
552
+ */
553
+ readonly libraryUrl: "https://arrecife.eduardoalvarez.dev";
541
554
  };
542
555
  type ColorMode = keyof typeof colors;
543
556
  type ColorToken = keyof typeof dark;
@@ -782,6 +795,8 @@ declare const tokens: {
782
795
  readonly wordmark: "Eduardo Álvarez";
783
796
  readonly mascot: "Tiburoncín";
784
797
  readonly domain: "eduardoalvarez.dev";
798
+ readonly library: "Arrecife";
799
+ readonly libraryUrl: "https://arrecife.eduardoalvarez.dev";
785
800
  };
786
801
  };
787
802
  type Tokens = typeof tokens;
@@ -1,2 +1,2 @@
1
- export { tokens } from '../chunk-5A5GH2PF.js';
2
- export { brand, colors, control, dark, fonts, gradient, light, limits, motion, naming, radius, series, shadow, size, spacing, syntax, tagline, typeScale } from '../chunk-FGFNK72B.js';
1
+ export { tokens } from '../chunk-6QJQ6K7J.js';
2
+ export { brand, colors, control, dark, fonts, gradient, light, limits, motion, naming, radius, series, shadow, size, spacing, syntax, tagline, typeScale } from '../chunk-5YWGOFDX.js';
@@ -18,7 +18,24 @@
18
18
  @custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *));
19
19
  @custom-variant light (&:where([data-theme="light"], [data-theme="light"] *));
20
20
 
21
- @theme {
21
+ /* STATIC, and that word is the whole of a bug fix. Tailwind v4 emits a theme
22
+ variable only if some utility it generated uses it, and a token read with
23
+ var() from JS is asked for by no utility at all: seriesColor(i) returns
24
+ var(--color-series-N) on purpose, so the color follows the mode instead of
25
+ freezing to whichever one was live when the chart mounted. No project writes
26
+ bg-series-1, so Tailwind dropped all four as unused, the var() resolved to
27
+ nothing, and a fill that resolves to nothing is black — on a dark page,
28
+ indistinguishable from «no data». No error in the console and none in the
29
+ build; the report that arrived was «the information is not showing».
30
+
31
+ With static, every token this file declares reaches :root whether a class
32
+ asks for it or not, which is what a published token set is: a contract, not
33
+ a subset of itself discovered by usage. It costs CSS — measured at +1.6 KB
34
+ raw / +234 B gzipped for a project using the library's whole vocabulary, and
35
+ +3.2 KB / +579 B for one that writes almost nothing — and it buys the
36
+ removal of a whole class of silent failure rather than of one instance.
37
+ See docs/decisions/ § 61. */
38
+ @theme static {
22
39
  /* --- color · dark mode (default) ------------------------------------- */
23
40
  --color-background: #091319;
24
41
  --color-surface: #10202B;
@@ -265,7 +282,7 @@
265
282
  written from first principles about terminals rather than read off the two
266
283
  sites that already had a signature. A utility with no consumer and no origin
267
284
  is not a feature, it is the invention still sitting there under a new label.
268
- See docs/decisions/0.8.md § 45.
285
+ See docs/decisions/ § 45.
269
286
 
270
287
  Its reason is the one the other four exceptions share: it is feedback about
271
288
  PROGRESS. A prompt that radiates says the terminal is live, which is the same
@@ -283,7 +300,7 @@
283
300
  Behind motion-safe at the call site — the half NOT copied from cursos, whose
284
301
  span animates regardless. The blog guarded it, every other exception here is
285
302
  guarded, and at rest the bar is simply solid.
286
- See docs/decisions/0.8.md § 45. */
303
+ See docs/decisions/ § 45. */
287
304
  @keyframes arrecife-pulse {
288
305
  0%, 100% {
289
306
  box-shadow: 0 0 0 0 color-mix(in oklab, var(--color-accent) 70%, transparent);
@@ -21,7 +21,7 @@ var button = classVarianceAuthority.cva(
21
21
  ],
22
22
  // The one control whose focus ring is not biolume. It is the system's
23
23
  // only sand fill, and a biolume ring three pixels off a sand button puts
24
- // both of the brand's accents in the same glance. See `docs/decisions/0.7.md` § 37.
24
+ // both of the brand's accents in the same glance. See `docs/decisions/` § 37.
25
25
  conversion: "bg-warm text-warm-on hover:bg-warm-hover focus-ring-warm",
26
26
  secondary: [
27
27
  "border-hairline-hover border bg-transparent text-text-primary",
@@ -32,7 +32,7 @@ import * as class_variance_authority_types from 'class-variance-authority/types'
32
32
  * actions and toolbars, next to «Editar» and «Duplicar», with no context to tell
33
33
  * them apart: with every one rendered as `secondary`, «Eliminar curso» looked
34
34
  * exactly like «Cancelar» and only the word separated them. See
35
- * `docs/decisions/0.6.md` § 21.
35
+ * `docs/decisions/` § 21.
36
36
  *
37
37
  * `destructiveOutline` fills on hover, and that IS an exception to «secondary is
38
38
  * never filled» — declared here rather than discovered later. A destructive
@@ -151,7 +151,7 @@ declare const text: (props?: ({
151
151
  *
152
152
  * The radius: the document says 12, which is none of the system's five radii. It
153
153
  * uses the card radius rather than introducing a sixth — see
154
- * `docs/decisions/`.
154
+ * `docs/decisions/` § 3.
155
155
  */
156
156
  declare const alert: (props?: ({
157
157
  variant?: "error" | "accent" | "success" | "warning" | null | undefined;
@@ -32,7 +32,7 @@ import * as class_variance_authority_types from 'class-variance-authority/types'
32
32
  * actions and toolbars, next to «Editar» and «Duplicar», with no context to tell
33
33
  * them apart: with every one rendered as `secondary`, «Eliminar curso» looked
34
34
  * exactly like «Cancelar» and only the word separated them. See
35
- * `docs/decisions/0.6.md` § 21.
35
+ * `docs/decisions/` § 21.
36
36
  *
37
37
  * `destructiveOutline` fills on hover, and that IS an exception to «secondary is
38
38
  * never filled» — declared here rather than discovered later. A destructive
@@ -151,7 +151,7 @@ declare const text: (props?: ({
151
151
  *
152
152
  * The radius: the document says 12, which is none of the system's five radii. It
153
153
  * uses the card radius rather than introducing a sixth — see
154
- * `docs/decisions/`.
154
+ * `docs/decisions/` § 3.
155
155
  */
156
156
  declare const alert: (props?: ({
157
157
  variant?: "error" | "accent" | "success" | "warning" | null | undefined;
@@ -1,2 +1,2 @@
1
- export { CARD, CARD_HOVER, CARD_SURFACE, alert as alertVariants, avatar as avatarVariants, badge as badgeVariants, button as buttonVariants, category as categoryBadgeVariants, metric as metricBadgeVariants } from '../chunk-XXDATT3A.js';
1
+ export { CARD, CARD_HOVER, CARD_SURFACE, alert as alertVariants, avatar as avatarVariants, badge as badgeVariants, button as buttonVariants, category as categoryBadgeVariants, metric as metricBadgeVariants } from '../chunk-FF33ARRA.js';
2
2
  export { text as textVariants } from '../chunk-ODBFN44D.js';