@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
@@ -0,0 +1,195 @@
1
+ import * as class_variance_authority_types from 'class-variance-authority/types';
2
+
3
+ /**
4
+ * The system's FOUR variants, and only those four.
5
+ *
6
+ * Brand rule 2, as code rather than as documentation: in light mode the primary
7
+ * button cannot be biolume or sand, so it switches to solid hull. There is no
8
+ * literal hex anywhere — `brand.hull` is a token, and the hover reuses
9
+ * `textSecondary` instead of inventing a `hullHover`.
10
+ *
11
+ * Brand rule 3: `conversion` appears ONCE per screen. That is documented in the
12
+ * story and not enforced at runtime: two conversion buttons on one page are a
13
+ * design problem, not an error that should take the render down.
14
+ *
15
+ * `secondary` is NEVER filled. It is border and text: at rest, hover hairline
16
+ * and foam; on hover, both move to biolume. A filled secondary is a badly tinted
17
+ * primary, and that is what this file used to do.
18
+ *
19
+ * `tertiary` is the system's CLI aesthetic: mono, `./action →` format, no box.
20
+ * It shows up on every card, so it is not a generic `ghost` under another name —
21
+ * the text format is part of the variant.
22
+ *
23
+ * There ARE two danger variants, and they arrived the way the previous comment
24
+ * said they would: into the document first and in here second. The rule they
25
+ * replace — «the system's error lives in alerts and in field validation, not in
26
+ * a red button» — still holds INSIDE an `AlertDialog`, where a title explains
27
+ * what is about to happen, focus starts on cancel and clicking outside does not
28
+ * close it. The context does the work there and the confirm button is still not
29
+ * red.
30
+ *
31
+ * It stops holding in a table row. `cursos` has eight destructive buttons in row
32
+ * actions and toolbars, next to «Editar» and «Duplicar», with no context to tell
33
+ * them apart: with every one rendered as `secondary`, «Eliminar curso» looked
34
+ * exactly like «Cancelar» and only the word separated them. See
35
+ * `docs/decisions.md` § 21.
36
+ *
37
+ * `destructiveOutline` fills on hover, and that IS an exception to «secondary is
38
+ * never filled» — declared here rather than discovered later. A destructive
39
+ * button that looks identical to a secondary until you read it is the problem
40
+ * this variant exists to fix, and at rest it is still only border and text.
41
+ */
42
+ declare const button: (props?: ({
43
+ variant?: "primary" | "conversion" | "secondary" | "tertiary" | "destructive" | "destructiveOutline" | null | undefined;
44
+ size?: "sm" | "md" | "lg" | "icon" | "icon-sm" | null | undefined;
45
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
46
+
47
+ /**
48
+ * THREE badge families, not one.
49
+ *
50
+ * The system defines three distinct shapes and this file served all of them as a
51
+ * mono pill in small caps. Each has its own shape because each says a different
52
+ * thing:
53
+ *
54
+ * category · pill r999, mono 11.5, sand → a slug: `engineering-culture`
55
+ * status · square r6, sans 12.5/500, tint → a signal: published, draft
56
+ * metric · pill, mono 11.5 muted → a datum: `8 min read`
57
+ *
58
+ * NONE of them is small-capped. The `uppercase tracking-[0.12em]` all three used
59
+ * to carry came from `text-eyebrow`, which is the eyebrow scale and not the
60
+ * badge one: it turned `engineering-culture` into `ENGINEERING-CULTURE` and
61
+ * `pose-laptop-coffee.png` into a file name that does not exist.
62
+ */
63
+ /**
64
+ * A signal. Square r6, sans 12.5/500 and the semantic color at 8 % as the
65
+ * background — the alert recipe at word size: a status IS a one-word alert.
66
+ *
67
+ * NO border. It had one for a while, added to reinforce the tone, and it was
68
+ * heavy: a bordered box next to a title reads as a control and not as a datum.
69
+ * The tint alone is what the document asks for and it is what looks cleanest.
70
+ *
71
+ * The text is `textPrimary`, not the tone's color. In light mode the semantic
72
+ * colors are calibrated to pass JUST over paper, so over their own tint they
73
+ * fall to 4.10–4.40 and fail AA. The tint is a surface; what goes on top of it
74
+ * is a text token. Measured in `alert.tsx`.
75
+ *
76
+ * The tone is never the only carrier of meaning: the label spells out
77
+ * «Publicado» or «Borrador» in full.
78
+ */
79
+ declare const badge: (props?: ({
80
+ variant?: "error" | "neutral" | "accent" | "warm" | "success" | "warning" | null | undefined;
81
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
82
+ /**
83
+ * A slug, in sand. Untransformed: slugs already arrive lowercase and forcing it
84
+ * would be the same mistake the `uppercase` was making.
85
+ *
86
+ * The document's border is `#4A3A25`, which is sand at 28 % over abyss: it comes
87
+ * out of the palette, so it does not enter as a new token. In light mode the
88
+ * same rule gives dark sand at 28 % over paper, which is what is wanted.
89
+ *
90
+ * The filled variant is NOT decorative: it is the only indicator of the active
91
+ * filter in the article listing. That is why `active` is a prop and not a
92
+ * `className`.
93
+ */
94
+ declare const category: (props?: ({
95
+ active?: boolean | null | undefined;
96
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
97
+ /**
98
+ * A datum: reading minutes, number of modules, a file name.
99
+ *
100
+ * No color box and no transform. It is the family `brand.stories.tsx` was asking
101
+ * for when it rendered `LAPTOP-COFFEE` for a file name that is actually
102
+ * `pose-laptop-coffee.png`.
103
+ */
104
+ declare const metric: string[];
105
+
106
+ declare const text: (props?: ({
107
+ variant?: "display" | "stat" | "h1" | "h2" | "h3" | "body" | "lead" | "ui" | "label" | "tag" | "chip" | "meta" | "eyebrow" | null | undefined;
108
+ tone?: "error" | "primary" | "secondary" | "accent" | "warm" | "success" | "warning" | "muted" | null | undefined;
109
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
110
+
111
+ /**
112
+ * The alert carries its color in the background, not only in the border.
113
+ *
114
+ * The system recipe is the semantic color at 8 % as background and at 22 % as
115
+ * border. This file gave `bg-surface` to all four variants, so the tone lived
116
+ * entirely in a 1px border: four alerts told apart by a line.
117
+ *
118
+ * All four tones start at ACCENT, which is the system's informational one (✦).
119
+ * There is no `neutral`: an alert without color is a paragraph.
120
+ *
121
+ * MEASURED in both modes, because the document's 8 % is calculated over abyss
122
+ * and it had to be checked that it survives over paper. Contrast of the tint
123
+ * against the page background:
124
+ *
125
+ * 8 % dark 8 % light
126
+ * accent 1.149 1.106
127
+ * success 1.116 1.121
128
+ * warning 1.126 1.109
129
+ * error 1.067 1.120
130
+ *
131
+ * Light mode needs NO second table: it holds up as well as or better than dark.
132
+ * The system's only weak point is `error` over abyss, 1.067, the faintest of the
133
+ * eight tints, which leans entirely on the 22 % border.
134
+ *
135
+ * There is a SECOND recipe, deliberately: the alert under the newsletter form
136
+ * goes to 10 % with a solid border so it reads under the field. That is
137
+ * `emphasis="strong"`, and it is not merged with the subtle one because the
138
+ * difference is documented.
139
+ *
140
+ * A THIRD contrast correction, in the line of the three `tokens.ts` already
141
+ * carried. The title used to be in the semantic color, and in light mode that
142
+ * cannot pass AA: the light semantics are calibrated to pass JUST over paper
143
+ * (4.54–4.88), so over their own tint at 8 % they fall to 4.11–4.40. No alpha
144
+ * fixes it — the problem is putting the color on top of itself.
145
+ *
146
+ * The tint is a SURFACE, so the text on top of it is a text token:
147
+ * `textPrimary` gives 14.6–14.9 over all four tints. The semantic color stays
148
+ * where it is not text — the border and the glyph — which is all the document
149
+ * ever asked of it. The glyph is decorative and `aria-hidden`, so the 3:1
150
+ * threshold applies to it rather than 4.5: its worst light case is 4.11.
151
+ *
152
+ * The radius: the document says 12, which is none of the system's five radii. It
153
+ * uses the card radius rather than introducing a sixth — see
154
+ * `docs/decisions.md`.
155
+ */
156
+ declare const alert: (props?: ({
157
+ variant?: "error" | "accent" | "success" | "warning" | null | undefined;
158
+ emphasis?: "subtle" | "strong" | null | undefined;
159
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
160
+
161
+ declare const avatar: (props?: ({
162
+ size?: "sm" | "md" | "lg" | "xl" | null | undefined;
163
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
164
+
165
+ /**
166
+ * The card's class vocabulary, with no React attached.
167
+ *
168
+ * `CARD_SURFACE` is the system's only definition of what a card surface is:
169
+ * `surface`, `hairline` border, card radius. `CARD_HOVER` is rule 6 — the hover
170
+ * changes the border and nothing else. `CARD` is the two of them plus what a
171
+ * clickable card needs.
172
+ *
173
+ * They live here and not in `primitives/card.tsx` because `links` writes them by
174
+ * hand: that project ships no framework JavaScript and cannot import a
175
+ * component, so until now it copied the class list into its Astro. The copy had
176
+ * already drifted once — the hero gradient sat at `55%` and `#e9eeea` against
177
+ * the token's `60%` and, at the time, `#EFE9DE`. Nothing compared them. The
178
+ * light gradient's second stop is `#FFFFFF` since § 9 was measured, which is the
179
+ * same lesson from the other side: a copied value goes stale when the original
180
+ * moves, and only the original is ever right.
181
+ */
182
+ declare const CARD_SURFACE = "rounded-card border-hairline bg-surface border";
183
+ /** Rule 6's hover: the border only. Applied where the card is clickable. */
184
+ declare const CARD_HOVER = "transition-standard hover:border-hairline-hover";
185
+ /**
186
+ * The shared shell of the clickable cards — `ArticleCard`, `TalkCard`,
187
+ * `CourseCard`, `LinkRow` — so rule 6 lives in exactly one place.
188
+ *
189
+ * «States are communicated with border and color, not with movement. A card's
190
+ * hover changes the border from hairline to hairlineHover and nothing else.» No
191
+ * scale, no elevation, no title displacement.
192
+ */
193
+ declare const CARD: string[];
194
+
195
+ export { CARD, CARD_HOVER, CARD_SURFACE, alert as alertVariants, avatar as avatarVariants, badge as badgeVariants, button as buttonVariants, category as categoryBadgeVariants, metric as metricBadgeVariants, text as textVariants };
@@ -0,0 +1,195 @@
1
+ import * as class_variance_authority_types from 'class-variance-authority/types';
2
+
3
+ /**
4
+ * The system's FOUR variants, and only those four.
5
+ *
6
+ * Brand rule 2, as code rather than as documentation: in light mode the primary
7
+ * button cannot be biolume or sand, so it switches to solid hull. There is no
8
+ * literal hex anywhere — `brand.hull` is a token, and the hover reuses
9
+ * `textSecondary` instead of inventing a `hullHover`.
10
+ *
11
+ * Brand rule 3: `conversion` appears ONCE per screen. That is documented in the
12
+ * story and not enforced at runtime: two conversion buttons on one page are a
13
+ * design problem, not an error that should take the render down.
14
+ *
15
+ * `secondary` is NEVER filled. It is border and text: at rest, hover hairline
16
+ * and foam; on hover, both move to biolume. A filled secondary is a badly tinted
17
+ * primary, and that is what this file used to do.
18
+ *
19
+ * `tertiary` is the system's CLI aesthetic: mono, `./action →` format, no box.
20
+ * It shows up on every card, so it is not a generic `ghost` under another name —
21
+ * the text format is part of the variant.
22
+ *
23
+ * There ARE two danger variants, and they arrived the way the previous comment
24
+ * said they would: into the document first and in here second. The rule they
25
+ * replace — «the system's error lives in alerts and in field validation, not in
26
+ * a red button» — still holds INSIDE an `AlertDialog`, where a title explains
27
+ * what is about to happen, focus starts on cancel and clicking outside does not
28
+ * close it. The context does the work there and the confirm button is still not
29
+ * red.
30
+ *
31
+ * It stops holding in a table row. `cursos` has eight destructive buttons in row
32
+ * actions and toolbars, next to «Editar» and «Duplicar», with no context to tell
33
+ * them apart: with every one rendered as `secondary`, «Eliminar curso» looked
34
+ * exactly like «Cancelar» and only the word separated them. See
35
+ * `docs/decisions.md` § 21.
36
+ *
37
+ * `destructiveOutline` fills on hover, and that IS an exception to «secondary is
38
+ * never filled» — declared here rather than discovered later. A destructive
39
+ * button that looks identical to a secondary until you read it is the problem
40
+ * this variant exists to fix, and at rest it is still only border and text.
41
+ */
42
+ declare const button: (props?: ({
43
+ variant?: "primary" | "conversion" | "secondary" | "tertiary" | "destructive" | "destructiveOutline" | null | undefined;
44
+ size?: "sm" | "md" | "lg" | "icon" | "icon-sm" | null | undefined;
45
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
46
+
47
+ /**
48
+ * THREE badge families, not one.
49
+ *
50
+ * The system defines three distinct shapes and this file served all of them as a
51
+ * mono pill in small caps. Each has its own shape because each says a different
52
+ * thing:
53
+ *
54
+ * category · pill r999, mono 11.5, sand → a slug: `engineering-culture`
55
+ * status · square r6, sans 12.5/500, tint → a signal: published, draft
56
+ * metric · pill, mono 11.5 muted → a datum: `8 min read`
57
+ *
58
+ * NONE of them is small-capped. The `uppercase tracking-[0.12em]` all three used
59
+ * to carry came from `text-eyebrow`, which is the eyebrow scale and not the
60
+ * badge one: it turned `engineering-culture` into `ENGINEERING-CULTURE` and
61
+ * `pose-laptop-coffee.png` into a file name that does not exist.
62
+ */
63
+ /**
64
+ * A signal. Square r6, sans 12.5/500 and the semantic color at 8 % as the
65
+ * background — the alert recipe at word size: a status IS a one-word alert.
66
+ *
67
+ * NO border. It had one for a while, added to reinforce the tone, and it was
68
+ * heavy: a bordered box next to a title reads as a control and not as a datum.
69
+ * The tint alone is what the document asks for and it is what looks cleanest.
70
+ *
71
+ * The text is `textPrimary`, not the tone's color. In light mode the semantic
72
+ * colors are calibrated to pass JUST over paper, so over their own tint they
73
+ * fall to 4.10–4.40 and fail AA. The tint is a surface; what goes on top of it
74
+ * is a text token. Measured in `alert.tsx`.
75
+ *
76
+ * The tone is never the only carrier of meaning: the label spells out
77
+ * «Publicado» or «Borrador» in full.
78
+ */
79
+ declare const badge: (props?: ({
80
+ variant?: "error" | "neutral" | "accent" | "warm" | "success" | "warning" | null | undefined;
81
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
82
+ /**
83
+ * A slug, in sand. Untransformed: slugs already arrive lowercase and forcing it
84
+ * would be the same mistake the `uppercase` was making.
85
+ *
86
+ * The document's border is `#4A3A25`, which is sand at 28 % over abyss: it comes
87
+ * out of the palette, so it does not enter as a new token. In light mode the
88
+ * same rule gives dark sand at 28 % over paper, which is what is wanted.
89
+ *
90
+ * The filled variant is NOT decorative: it is the only indicator of the active
91
+ * filter in the article listing. That is why `active` is a prop and not a
92
+ * `className`.
93
+ */
94
+ declare const category: (props?: ({
95
+ active?: boolean | null | undefined;
96
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
97
+ /**
98
+ * A datum: reading minutes, number of modules, a file name.
99
+ *
100
+ * No color box and no transform. It is the family `brand.stories.tsx` was asking
101
+ * for when it rendered `LAPTOP-COFFEE` for a file name that is actually
102
+ * `pose-laptop-coffee.png`.
103
+ */
104
+ declare const metric: string[];
105
+
106
+ declare const text: (props?: ({
107
+ variant?: "display" | "stat" | "h1" | "h2" | "h3" | "body" | "lead" | "ui" | "label" | "tag" | "chip" | "meta" | "eyebrow" | null | undefined;
108
+ tone?: "error" | "primary" | "secondary" | "accent" | "warm" | "success" | "warning" | "muted" | null | undefined;
109
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
110
+
111
+ /**
112
+ * The alert carries its color in the background, not only in the border.
113
+ *
114
+ * The system recipe is the semantic color at 8 % as background and at 22 % as
115
+ * border. This file gave `bg-surface` to all four variants, so the tone lived
116
+ * entirely in a 1px border: four alerts told apart by a line.
117
+ *
118
+ * All four tones start at ACCENT, which is the system's informational one (✦).
119
+ * There is no `neutral`: an alert without color is a paragraph.
120
+ *
121
+ * MEASURED in both modes, because the document's 8 % is calculated over abyss
122
+ * and it had to be checked that it survives over paper. Contrast of the tint
123
+ * against the page background:
124
+ *
125
+ * 8 % dark 8 % light
126
+ * accent 1.149 1.106
127
+ * success 1.116 1.121
128
+ * warning 1.126 1.109
129
+ * error 1.067 1.120
130
+ *
131
+ * Light mode needs NO second table: it holds up as well as or better than dark.
132
+ * The system's only weak point is `error` over abyss, 1.067, the faintest of the
133
+ * eight tints, which leans entirely on the 22 % border.
134
+ *
135
+ * There is a SECOND recipe, deliberately: the alert under the newsletter form
136
+ * goes to 10 % with a solid border so it reads under the field. That is
137
+ * `emphasis="strong"`, and it is not merged with the subtle one because the
138
+ * difference is documented.
139
+ *
140
+ * A THIRD contrast correction, in the line of the three `tokens.ts` already
141
+ * carried. The title used to be in the semantic color, and in light mode that
142
+ * cannot pass AA: the light semantics are calibrated to pass JUST over paper
143
+ * (4.54–4.88), so over their own tint at 8 % they fall to 4.11–4.40. No alpha
144
+ * fixes it — the problem is putting the color on top of itself.
145
+ *
146
+ * The tint is a SURFACE, so the text on top of it is a text token:
147
+ * `textPrimary` gives 14.6–14.9 over all four tints. The semantic color stays
148
+ * where it is not text — the border and the glyph — which is all the document
149
+ * ever asked of it. The glyph is decorative and `aria-hidden`, so the 3:1
150
+ * threshold applies to it rather than 4.5: its worst light case is 4.11.
151
+ *
152
+ * The radius: the document says 12, which is none of the system's five radii. It
153
+ * uses the card radius rather than introducing a sixth — see
154
+ * `docs/decisions.md`.
155
+ */
156
+ declare const alert: (props?: ({
157
+ variant?: "error" | "accent" | "success" | "warning" | null | undefined;
158
+ emphasis?: "subtle" | "strong" | null | undefined;
159
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
160
+
161
+ declare const avatar: (props?: ({
162
+ size?: "sm" | "md" | "lg" | "xl" | null | undefined;
163
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
164
+
165
+ /**
166
+ * The card's class vocabulary, with no React attached.
167
+ *
168
+ * `CARD_SURFACE` is the system's only definition of what a card surface is:
169
+ * `surface`, `hairline` border, card radius. `CARD_HOVER` is rule 6 — the hover
170
+ * changes the border and nothing else. `CARD` is the two of them plus what a
171
+ * clickable card needs.
172
+ *
173
+ * They live here and not in `primitives/card.tsx` because `links` writes them by
174
+ * hand: that project ships no framework JavaScript and cannot import a
175
+ * component, so until now it copied the class list into its Astro. The copy had
176
+ * already drifted once — the hero gradient sat at `55%` and `#e9eeea` against
177
+ * the token's `60%` and, at the time, `#EFE9DE`. Nothing compared them. The
178
+ * light gradient's second stop is `#FFFFFF` since § 9 was measured, which is the
179
+ * same lesson from the other side: a copied value goes stale when the original
180
+ * moves, and only the original is ever right.
181
+ */
182
+ declare const CARD_SURFACE = "rounded-card border-hairline bg-surface border";
183
+ /** Rule 6's hover: the border only. Applied where the card is clickable. */
184
+ declare const CARD_HOVER = "transition-standard hover:border-hairline-hover";
185
+ /**
186
+ * The shared shell of the clickable cards — `ArticleCard`, `TalkCard`,
187
+ * `CourseCard`, `LinkRow` — so rule 6 lives in exactly one place.
188
+ *
189
+ * «States are communicated with border and color, not with movement. A card's
190
+ * hover changes the border from hairline to hairlineHover and nothing else.» No
191
+ * scale, no elevation, no title displacement.
192
+ */
193
+ declare const CARD: string[];
194
+
195
+ export { CARD, CARD_HOVER, CARD_SURFACE, alert as alertVariants, avatar as avatarVariants, badge as badgeVariants, button as buttonVariants, category as categoryBadgeVariants, metric as metricBadgeVariants, text as textVariants };
@@ -0,0 +1,3 @@
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-E6KFUSKB.js';
2
+ export { text as textVariants } from '../chunk-ODBFN44D.js';
3
+ import '../chunk-MLKGABMK.js';