@veluai/velu 0.2.13 → 0.2.15

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 (109) hide show
  1. package/README.md +80 -80
  2. package/dist/cli.js +37 -37
  3. package/package.json +64 -64
  4. package/runtime/velu-ui/base.css +320 -320
  5. package/runtime/velu-ui/components/Accordion.jsx +64 -64
  6. package/runtime/velu-ui/components/ApiClient.jsx +207 -207
  7. package/runtime/velu-ui/components/ApiField.jsx +87 -87
  8. package/runtime/velu-ui/components/ApiPath.jsx +63 -63
  9. package/runtime/velu-ui/components/ApiReferencePage.jsx +384 -384
  10. package/runtime/velu-ui/components/ApiSamples.jsx +36 -36
  11. package/runtime/velu-ui/components/ApiSidebar.jsx +122 -122
  12. package/runtime/velu-ui/components/AskBar.jsx +71 -71
  13. package/runtime/velu-ui/components/Callout.jsx +114 -114
  14. package/runtime/velu-ui/components/Card.jsx +131 -131
  15. package/runtime/velu-ui/components/Chatbot.jsx +885 -885
  16. package/runtime/velu-ui/components/CodeBlock.jsx +375 -375
  17. package/runtime/velu-ui/components/Columns.jsx +56 -56
  18. package/runtime/velu-ui/components/ContextMenu.jsx +298 -273
  19. package/runtime/velu-ui/components/ErrorCard.jsx +138 -138
  20. package/runtime/velu-ui/components/Field.jsx +81 -81
  21. package/runtime/velu-ui/components/Image.jsx +163 -163
  22. package/runtime/velu-ui/components/Logo.jsx +31 -31
  23. package/runtime/velu-ui/components/MethodBadge.jsx +31 -31
  24. package/runtime/velu-ui/components/NavSelect.jsx +108 -108
  25. package/runtime/velu-ui/components/NotFound.jsx +63 -63
  26. package/runtime/velu-ui/components/PageFeedback.jsx +219 -219
  27. package/runtime/velu-ui/components/PageFooter.jsx +145 -145
  28. package/runtime/velu-ui/components/PageHeader.jsx +422 -422
  29. package/runtime/velu-ui/components/PageNav.jsx +77 -77
  30. package/runtime/velu-ui/components/PoweredBy.jsx +51 -51
  31. package/runtime/velu-ui/components/Prompt.jsx +115 -115
  32. package/runtime/velu-ui/components/Search.jsx +460 -460
  33. package/runtime/velu-ui/components/Sidebar.jsx +254 -254
  34. package/runtime/velu-ui/components/SocialLinks.jsx +90 -90
  35. package/runtime/velu-ui/components/Steps.jsx +65 -65
  36. package/runtime/velu-ui/components/ThemeToggle.jsx +48 -48
  37. package/runtime/velu-ui/components/Toc.jsx +537 -537
  38. package/runtime/velu-ui/components/TocBar.jsx +195 -195
  39. package/runtime/velu-ui/components/Tree.jsx +87 -87
  40. package/runtime/velu-ui/components/TryItBar.jsx +102 -102
  41. package/runtime/velu-ui/components/accordion.css +92 -92
  42. package/runtime/velu-ui/components/api-page.css +208 -208
  43. package/runtime/velu-ui/components/api.css +635 -635
  44. package/runtime/velu-ui/components/ask-bar.css +94 -94
  45. package/runtime/velu-ui/components/card.css +105 -105
  46. package/runtime/velu-ui/components/chatbot.css +622 -622
  47. package/runtime/velu-ui/components/code-block.css +263 -263
  48. package/runtime/velu-ui/components/context-menu.css +173 -173
  49. package/runtime/velu-ui/components/docs-layout.css +822 -822
  50. package/runtime/velu-ui/components/field.css +82 -82
  51. package/runtime/velu-ui/components/image.css +237 -237
  52. package/runtime/velu-ui/components/nav-select.css +157 -157
  53. package/runtime/velu-ui/components/not-found.css +94 -94
  54. package/runtime/velu-ui/components/page-feedback.css +241 -241
  55. package/runtime/velu-ui/components/page-footer.css +130 -130
  56. package/runtime/velu-ui/components/page-header.css +558 -558
  57. package/runtime/velu-ui/components/page-nav.css +50 -50
  58. package/runtime/velu-ui/components/powered-by.css +92 -92
  59. package/runtime/velu-ui/components/prompt.css +99 -99
  60. package/runtime/velu-ui/components/search.css +307 -307
  61. package/runtime/velu-ui/components/sidebar.css +205 -205
  62. package/runtime/velu-ui/components/steps.css +77 -77
  63. package/runtime/velu-ui/components/theme-toggle.css +102 -102
  64. package/runtime/velu-ui/components/toc-bar.css +234 -234
  65. package/runtime/velu-ui/components/tree.css +49 -49
  66. package/runtime/velu-ui/index.js +54 -54
  67. package/runtime/velu-ui/lib/api-send.js +92 -92
  68. package/runtime/velu-ui/lib/brand-icons.jsx +103 -103
  69. package/runtime/velu-ui/lib/component-schemas.js +100 -100
  70. package/runtime/velu-ui/lib/copyText.js +64 -64
  71. package/runtime/velu-ui/lib/docs-assistant.js +250 -250
  72. package/runtime/velu-ui/lib/lang-icons.jsx +147 -147
  73. package/runtime/velu-ui/lib/pagefind.js +113 -113
  74. package/runtime/velu-ui/lib/prism-langs.js +957 -957
  75. package/runtime/velu-ui/lib/prism-loader.js +74 -74
  76. package/runtime/velu-ui/lib/resolveIcon.jsx +29 -29
  77. package/runtime/velu-ui/lib/scrollIntoNearestView.js +66 -66
  78. package/runtime/velu-ui/mdx-components.jsx +105 -105
  79. package/runtime/velu-ui/primitives/Cluster.jsx +49 -49
  80. package/runtime/velu-ui/primitives/Stack.jsx +63 -63
  81. package/runtime/velu-ui/primitives/Switcher.jsx +57 -57
  82. package/runtime/velu-ui/primitives/stack.css +3 -3
  83. package/runtime/velu-ui/primitives/switcher.css +25 -25
  84. package/runtime/velu-ui/styles.css +46 -46
  85. package/runtime/velu-ui/tokens.css +4 -4
  86. package/schema/velu.schema.json +423 -423
  87. package/src/lib/extract-mdx-error.js +170 -170
  88. package/src/lib/issues.js +159 -159
  89. package/src/lib/known-components.js +34 -34
  90. package/src/navigation.js +443 -443
  91. package/src/runtime/App.jsx +1669 -1668
  92. package/src/runtime/ErrorBoundary.jsx +54 -54
  93. package/src/runtime/client-entry.jsx +22 -22
  94. package/src/runtime/server-entry.jsx +16 -16
  95. package/src/template.html +48 -48
  96. package/templates/starter/ai-tools/claude-code.mdx +26 -26
  97. package/templates/starter/ai-tools/cursor.mdx +17 -17
  98. package/templates/starter/api-reference/introduction.mdx +43 -43
  99. package/templates/starter/development.mdx +19 -19
  100. package/templates/starter/essentials/code.mdx +29 -29
  101. package/templates/starter/essentials/images.mdx +29 -29
  102. package/templates/starter/essentials/markdown.mdx +25 -25
  103. package/templates/starter/essentials/navigation.mdx +39 -39
  104. package/templates/starter/essentials/settings.mdx +30 -30
  105. package/templates/starter/favicon.svg +6 -6
  106. package/templates/starter/index.mdx +31 -31
  107. package/templates/starter/openapi.json +160 -160
  108. package/templates/starter/quickstart.mdx +31 -31
  109. package/templates/starter/velu.json +41 -41
@@ -1,205 +1,205 @@
1
- /* Sidebar — sidebar-specific styling ONLY.
2
-
3
- Vertical rhythm (nav, section lists, nested sublists) is composed from the
4
- Stack primitive in Sidebar.jsx (DRY) — Stack supplies display/flex/gap
5
- inline. This file holds only what Stack cannot express: the indent rails,
6
- active accent rail, the horizontal item rows, summary marker, chevron
7
- rotation, and centralized icon sizing/stroke. All values are tokens. */
8
-
9
- .velu-sidebar {
10
- position: relative; /* anchors the gliding active indicator */
11
- margin-left: var(--s1);
12
- }
13
-
14
- /* The single active indicator — a crimson tint band with a flush-left 2px bar
15
- that GLIDES between items (one element animating its position/height) instead
16
- of each item painting its own active state. z-index 0 keeps it BEHIND the
17
- items + sticky headings (both positioned, z-index 1), so the text reads over
18
- the tint and a pinned heading's opaque background covers the indicator when an
19
- item scrolls under it. Driven imperatively from JS (transform/height/opacity);
20
- the easing curve makes the slide feel continuous. */
21
- .velu-sidebar__indicator {
22
- position: absolute;
23
- inset-inline-start: 0;
24
- inset-inline-end: var(--s-3);
25
- inset-block-start: 0;
26
- height: 0;
27
- opacity: 0;
28
- z-index: 0;
29
- pointer-events: none;
30
- background: color-mix(in srgb, var(--accent-color) 8%, transparent);
31
- border-radius: var(--radius-sm);
32
- transition:
33
- transform 0.3s cubic-bezier(0.32, 0.72, 0, 1),
34
- height 0.3s cubic-bezier(0.32, 0.72, 0, 1),
35
- opacity 0.2s ease;
36
- will-change: transform, height;
37
- }
38
- .velu-sidebar__indicator::before {
39
- content: '';
40
- position: absolute;
41
- inset-inline-start: 0;
42
- inset-block: 15%;
43
- inline-size: 2px;
44
- border-start-end-radius: 2px;
45
- border-end-end-radius: 2px;
46
- background: var(--accent-color);
47
- }
48
- /* Honour reduced-motion: snap instead of glide. */
49
- @media (prefers-reduced-motion: reduce) {
50
- .velu-sidebar__indicator {
51
- transition: opacity 0.2s ease;
52
- }
53
- }
54
-
55
- .velu-sidebar__section {
56
- /* Sticky section header: each heading pins to the top of the scroll
57
- region until its own section scrolls past, then the next heading
58
- takes over (iOS-list style). It sticks within its section wrapper
59
- (Sidebar.jsx renders each section in its own Stack), which bounds
60
- the push-out. Full-width opaque background so scrolling items
61
- don't show behind it; --page-bg matches the surroundings, so the
62
- bar is invisible until it's actually covering scrolled content. */
63
- position: sticky;
64
- inset-block-start: 0;
65
- /* Above the items (z-index 1) so scrolled rows tuck UNDER the heading (its
66
- opaque bg + the ::after fade hide them), not over it; above the gliding
67
- indicator (z-index 0) too. */
68
- z-index: 2;
69
- background: var(--page-bg);
70
- display: flex;
71
- align-items: center;
72
- gap: var(--s-2);
73
- padding-block: var(--s-4);
74
- padding-inline: var(--s-3);
75
- /* A notch smaller than the default h5, with a little tracking so the
76
- uppercase label stays legible at the reduced size. */
77
- font-size: var(--f-h6);
78
- font-weight: 500;
79
- letter-spacing: 0.02em;
80
- text-transform: uppercase;
81
- }
82
- /* Fade zone just below the pinned heading: a gradient overlay
83
- (page-bg → transparent) that sits directly under the sticky header
84
- and scrolls with it. Items sliding up pass behind it and fade out
85
- before they tuck under the (crisp) heading. Absolutely positioned
86
- so it adds no resting layout space; pointer-events:none so it never
87
- eats clicks. Hidden by default — only shown once the nav is actually
88
- scrolled (the layout toggles it via data-fade-top on the scroll
89
- region), so a section's first item isn't faded at rest. */
90
- .velu-sidebar__section::after {
91
- content: '';
92
- position: absolute;
93
- inset-inline: 0;
94
- inset-block-start: 100%;
95
- block-size: var(--s3);
96
- background: linear-gradient(
97
- to bottom,
98
- var(--page-bg),
99
- color-mix(in srgb, var(--page-bg) 55%, transparent),
100
- transparent
101
- );
102
- pointer-events: none;
103
- opacity: 0;
104
- transition: opacity 0.15s ease;
105
- }
106
- /* When a heading becomes the newly-pinned one (data-stuck set by the
107
- runtime as you scroll past sections), fade + slide it in so the
108
- handoff from the previous heading reads as a transition rather than
109
- a hard swap. */
110
- .velu-sidebar__section[data-stuck='true'] {
111
- animation: velu-sidebar-stick-in 0.2s ease;
112
- }
113
- @keyframes velu-sidebar-stick-in {
114
- from {
115
- opacity: 0.3;
116
- transform: translateY(-0.2rem);
117
- }
118
- to {
119
- opacity: 1;
120
- transform: translateY(0);
121
- }
122
- }
123
-
124
- /* Lists are Stacks (flex/gap come from Stack inline) — only reset list chrome. */
125
- .velu-sidebar__list,
126
- .velu-sidebar__sublist {
127
- list-style: none;
128
- margin: 0;
129
- padding: 0;
130
- }
131
-
132
- .velu-sidebar__sublist {
133
- margin-left: var(--s0);
134
- border-left: var(--border-width) solid var(--border-color);
135
- }
136
-
137
- /* Item rows are horizontal (icon · label · chevron) — Stack is vertical-only,
138
- so these stay CSS until/if a Cluster/Inline primitive exists. */
139
- .velu-sidebar__item,
140
- .velu-sidebar__subitem {
141
- /* Positioned above the gliding indicator (z-index 0) so the label reads over
142
- the tint band. */
143
- position: relative;
144
- z-index: 1;
145
- display: flex;
146
- align-items: center;
147
- gap: var(--s-3);
148
- padding-inline: var(--s0);
149
- color: var(--text-color);
150
- text-decoration: none;
151
- transition: color 0.2s ease;
152
- }
153
-
154
- .velu-sidebar__subitem {
155
- padding-block: var(--s-5);
156
- }
157
-
158
- /* Active = colour + weight only; the moving indicator paints the bar + tint. */
159
- .velu-sidebar__item--active {
160
- color: var(--accent-color);
161
- font-weight: 500;
162
- }
163
- .velu-sidebar__item--active .velu-sidebar__icon {
164
- color: var(--accent-color);
165
- }
166
-
167
- /* The label fills the row so the group chevron (and any external-link icon)
168
- sit flush at the row's RIGHT end, not crowded against the label — faithful
169
- to the design's `flex: 1` label. */
170
- .velu-sidebar__label {
171
- flex: 1;
172
- min-inline-size: 0;
173
- }
174
-
175
- .velu-sidebar__summary {
176
- cursor: pointer;
177
- list-style: none;
178
- }
179
- .velu-sidebar__summary::-webkit-details-marker {
180
- display: none;
181
- }
182
-
183
- /* Icon sizing centralized here; stroke weight is the global --icon-stroke
184
- token (.lucide rule in base.css), not set per-component. */
185
- .velu-sidebar__icon {
186
- display: inline-flex;
187
- flex: none;
188
- inline-size: var(--f-body);
189
- block-size: var(--f-body);
190
- }
191
- .velu-sidebar__icon svg {
192
- inline-size: 100%;
193
- block-size: 100%;
194
- }
195
-
196
- .velu-sidebar__chevron {
197
- flex: none;
198
- inline-size: var(--f-body);
199
- block-size: var(--f-body);
200
- transition: transform 0.15s ease;
201
- }
202
-
203
- details[open] > .velu-sidebar__summary .velu-sidebar__chevron {
204
- transform: rotate(90deg);
205
- }
1
+ /* Sidebar — sidebar-specific styling ONLY.
2
+
3
+ Vertical rhythm (nav, section lists, nested sublists) is composed from the
4
+ Stack primitive in Sidebar.jsx (DRY) — Stack supplies display/flex/gap
5
+ inline. This file holds only what Stack cannot express: the indent rails,
6
+ active accent rail, the horizontal item rows, summary marker, chevron
7
+ rotation, and centralized icon sizing/stroke. All values are tokens. */
8
+
9
+ .velu-sidebar {
10
+ position: relative; /* anchors the gliding active indicator */
11
+ margin-left: var(--s1);
12
+ }
13
+
14
+ /* The single active indicator — a crimson tint band with a flush-left 2px bar
15
+ that GLIDES between items (one element animating its position/height) instead
16
+ of each item painting its own active state. z-index 0 keeps it BEHIND the
17
+ items + sticky headings (both positioned, z-index 1), so the text reads over
18
+ the tint and a pinned heading's opaque background covers the indicator when an
19
+ item scrolls under it. Driven imperatively from JS (transform/height/opacity);
20
+ the easing curve makes the slide feel continuous. */
21
+ .velu-sidebar__indicator {
22
+ position: absolute;
23
+ inset-inline-start: 0;
24
+ inset-inline-end: var(--s-3);
25
+ inset-block-start: 0;
26
+ height: 0;
27
+ opacity: 0;
28
+ z-index: 0;
29
+ pointer-events: none;
30
+ background: color-mix(in srgb, var(--accent-color) 8%, transparent);
31
+ border-radius: var(--radius-sm);
32
+ transition:
33
+ transform 0.3s cubic-bezier(0.32, 0.72, 0, 1),
34
+ height 0.3s cubic-bezier(0.32, 0.72, 0, 1),
35
+ opacity 0.2s ease;
36
+ will-change: transform, height;
37
+ }
38
+ .velu-sidebar__indicator::before {
39
+ content: '';
40
+ position: absolute;
41
+ inset-inline-start: 0;
42
+ inset-block: 15%;
43
+ inline-size: 2px;
44
+ border-start-end-radius: 2px;
45
+ border-end-end-radius: 2px;
46
+ background: var(--accent-color);
47
+ }
48
+ /* Honour reduced-motion: snap instead of glide. */
49
+ @media (prefers-reduced-motion: reduce) {
50
+ .velu-sidebar__indicator {
51
+ transition: opacity 0.2s ease;
52
+ }
53
+ }
54
+
55
+ .velu-sidebar__section {
56
+ /* Sticky section header: each heading pins to the top of the scroll
57
+ region until its own section scrolls past, then the next heading
58
+ takes over (iOS-list style). It sticks within its section wrapper
59
+ (Sidebar.jsx renders each section in its own Stack), which bounds
60
+ the push-out. Full-width opaque background so scrolling items
61
+ don't show behind it; --page-bg matches the surroundings, so the
62
+ bar is invisible until it's actually covering scrolled content. */
63
+ position: sticky;
64
+ inset-block-start: 0;
65
+ /* Above the items (z-index 1) so scrolled rows tuck UNDER the heading (its
66
+ opaque bg + the ::after fade hide them), not over it; above the gliding
67
+ indicator (z-index 0) too. */
68
+ z-index: 2;
69
+ background: var(--page-bg);
70
+ display: flex;
71
+ align-items: center;
72
+ gap: var(--s-2);
73
+ padding-block: var(--s-4);
74
+ padding-inline: var(--s-3);
75
+ /* A notch smaller than the default h5, with a little tracking so the
76
+ uppercase label stays legible at the reduced size. */
77
+ font-size: var(--f-h6);
78
+ font-weight: 500;
79
+ letter-spacing: 0.02em;
80
+ text-transform: uppercase;
81
+ }
82
+ /* Fade zone just below the pinned heading: a gradient overlay
83
+ (page-bg → transparent) that sits directly under the sticky header
84
+ and scrolls with it. Items sliding up pass behind it and fade out
85
+ before they tuck under the (crisp) heading. Absolutely positioned
86
+ so it adds no resting layout space; pointer-events:none so it never
87
+ eats clicks. Hidden by default — only shown once the nav is actually
88
+ scrolled (the layout toggles it via data-fade-top on the scroll
89
+ region), so a section's first item isn't faded at rest. */
90
+ .velu-sidebar__section::after {
91
+ content: '';
92
+ position: absolute;
93
+ inset-inline: 0;
94
+ inset-block-start: 100%;
95
+ block-size: var(--s3);
96
+ background: linear-gradient(
97
+ to bottom,
98
+ var(--page-bg),
99
+ color-mix(in srgb, var(--page-bg) 55%, transparent),
100
+ transparent
101
+ );
102
+ pointer-events: none;
103
+ opacity: 0;
104
+ transition: opacity 0.15s ease;
105
+ }
106
+ /* When a heading becomes the newly-pinned one (data-stuck set by the
107
+ runtime as you scroll past sections), fade + slide it in so the
108
+ handoff from the previous heading reads as a transition rather than
109
+ a hard swap. */
110
+ .velu-sidebar__section[data-stuck='true'] {
111
+ animation: velu-sidebar-stick-in 0.2s ease;
112
+ }
113
+ @keyframes velu-sidebar-stick-in {
114
+ from {
115
+ opacity: 0.3;
116
+ transform: translateY(-0.2rem);
117
+ }
118
+ to {
119
+ opacity: 1;
120
+ transform: translateY(0);
121
+ }
122
+ }
123
+
124
+ /* Lists are Stacks (flex/gap come from Stack inline) — only reset list chrome. */
125
+ .velu-sidebar__list,
126
+ .velu-sidebar__sublist {
127
+ list-style: none;
128
+ margin: 0;
129
+ padding: 0;
130
+ }
131
+
132
+ .velu-sidebar__sublist {
133
+ margin-left: var(--s0);
134
+ border-left: var(--border-width) solid var(--border-color);
135
+ }
136
+
137
+ /* Item rows are horizontal (icon · label · chevron) — Stack is vertical-only,
138
+ so these stay CSS until/if a Cluster/Inline primitive exists. */
139
+ .velu-sidebar__item,
140
+ .velu-sidebar__subitem {
141
+ /* Positioned above the gliding indicator (z-index 0) so the label reads over
142
+ the tint band. */
143
+ position: relative;
144
+ z-index: 1;
145
+ display: flex;
146
+ align-items: center;
147
+ gap: var(--s-3);
148
+ padding-inline: var(--s0);
149
+ color: var(--text-color);
150
+ text-decoration: none;
151
+ transition: color 0.2s ease;
152
+ }
153
+
154
+ .velu-sidebar__subitem {
155
+ padding-block: var(--s-5);
156
+ }
157
+
158
+ /* Active = colour + weight only; the moving indicator paints the bar + tint. */
159
+ .velu-sidebar__item--active {
160
+ color: var(--accent-color);
161
+ font-weight: 500;
162
+ }
163
+ .velu-sidebar__item--active .velu-sidebar__icon {
164
+ color: var(--accent-color);
165
+ }
166
+
167
+ /* The label fills the row so the group chevron (and any external-link icon)
168
+ sit flush at the row's RIGHT end, not crowded against the label — faithful
169
+ to the design's `flex: 1` label. */
170
+ .velu-sidebar__label {
171
+ flex: 1;
172
+ min-inline-size: 0;
173
+ }
174
+
175
+ .velu-sidebar__summary {
176
+ cursor: pointer;
177
+ list-style: none;
178
+ }
179
+ .velu-sidebar__summary::-webkit-details-marker {
180
+ display: none;
181
+ }
182
+
183
+ /* Icon sizing centralized here; stroke weight is the global --icon-stroke
184
+ token (.lucide rule in base.css), not set per-component. */
185
+ .velu-sidebar__icon {
186
+ display: inline-flex;
187
+ flex: none;
188
+ inline-size: var(--f-body);
189
+ block-size: var(--f-body);
190
+ }
191
+ .velu-sidebar__icon svg {
192
+ inline-size: 100%;
193
+ block-size: 100%;
194
+ }
195
+
196
+ .velu-sidebar__chevron {
197
+ flex: none;
198
+ inline-size: var(--f-body);
199
+ block-size: var(--f-body);
200
+ transition: transform 0.15s ease;
201
+ }
202
+
203
+ details[open] > .velu-sidebar__summary .velu-sidebar__chevron {
204
+ transform: rotate(90deg);
205
+ }
@@ -1,77 +1,77 @@
1
- /* Steps — numbered procedural list with a continuous accent rail
2
- running through every step's left margin. All values are tokens;
3
- light/dark via [data-theme]. */
4
-
5
- .velu-steps {
6
- display: block;
7
- }
8
-
9
- /* Each step is a 2-col / 2-row grid placed explicitly:
10
-
11
- col 1 col 2
12
- ┌──────────────────┬────────────────────┐
13
- │ circle (row 1, │ title (row 1, │
14
- │ align-self: end) │ align-self: end) │
15
- ├──────────────────┼────────────────────┤
16
- │ line (row 2, │ body (row 2) │
17
- │ 100% block-size) │ │
18
- └──────────────────┴────────────────────┘
19
-
20
- `align-self: end` on both row-1 items puts the circle's bottom and
21
- the title's bottom flush together — so an oversize circle no longer
22
- hovers above the title. Row 1 height is whichever child is taller
23
- (the circle). row-gap stays at 0 so the line touches the next step's
24
- circle with no visible break in the rail. */
25
- .velu-step {
26
- display: grid;
27
- grid-template-columns: var(--step-circle, 2em) 1fr;
28
- column-gap: var(--s0);
29
- row-gap: 0;
30
- }
31
-
32
- .velu-step__circle {
33
- grid-row: 1;
34
- grid-column: 1;
35
- align-self: center;
36
- justify-self: center;
37
- inline-size: var(--step-circle, 2em);
38
- block-size: var(--step-circle, 2em);
39
- border-radius: 50%;
40
- background: var(--accent-color);
41
- color: var(--page-bg);
42
- display: inline-flex;
43
- align-items: center;
44
- justify-content: center;
45
- font-size: var(--f-h6);
46
- line-height: 1;
47
- font-weight: var(--weight-medium);
48
- }
49
-
50
- .velu-step__line {
51
- grid-row: 2;
52
- grid-column: 1;
53
- justify-self: center;
54
- inline-size: 2px;
55
- block-size: 100%;
56
- min-block-size: var(--s2);
57
- background: var(--accent-color);
58
- }
59
-
60
- .velu-step__title {
61
- grid-row: 1;
62
- grid-column: 2;
63
- align-self: center;
64
- font-size: var(--f-h4);
65
- line-height: var(--lh-h4);
66
- font-weight: var(--weight-medium);
67
- color: var(--text-color);
68
- }
69
-
70
- .velu-step__body {
71
- grid-row: 2;
72
- grid-column: 2;
73
- padding-block: var(--s-1) var(--s2);
74
- color: var(--text-color);
75
- font-size: var(--f-body);
76
- line-height: var(--lh-body);
77
- }
1
+ /* Steps — numbered procedural list with a continuous accent rail
2
+ running through every step's left margin. All values are tokens;
3
+ light/dark via [data-theme]. */
4
+
5
+ .velu-steps {
6
+ display: block;
7
+ }
8
+
9
+ /* Each step is a 2-col / 2-row grid placed explicitly:
10
+
11
+ col 1 col 2
12
+ ┌──────────────────┬────────────────────┐
13
+ │ circle (row 1, │ title (row 1, │
14
+ │ align-self: end) │ align-self: end) │
15
+ ├──────────────────┼────────────────────┤
16
+ │ line (row 2, │ body (row 2) │
17
+ │ 100% block-size) │ │
18
+ └──────────────────┴────────────────────┘
19
+
20
+ `align-self: end` on both row-1 items puts the circle's bottom and
21
+ the title's bottom flush together — so an oversize circle no longer
22
+ hovers above the title. Row 1 height is whichever child is taller
23
+ (the circle). row-gap stays at 0 so the line touches the next step's
24
+ circle with no visible break in the rail. */
25
+ .velu-step {
26
+ display: grid;
27
+ grid-template-columns: var(--step-circle, 2em) 1fr;
28
+ column-gap: var(--s0);
29
+ row-gap: 0;
30
+ }
31
+
32
+ .velu-step__circle {
33
+ grid-row: 1;
34
+ grid-column: 1;
35
+ align-self: center;
36
+ justify-self: center;
37
+ inline-size: var(--step-circle, 2em);
38
+ block-size: var(--step-circle, 2em);
39
+ border-radius: 50%;
40
+ background: var(--accent-color);
41
+ color: var(--page-bg);
42
+ display: inline-flex;
43
+ align-items: center;
44
+ justify-content: center;
45
+ font-size: var(--f-h6);
46
+ line-height: 1;
47
+ font-weight: var(--weight-medium);
48
+ }
49
+
50
+ .velu-step__line {
51
+ grid-row: 2;
52
+ grid-column: 1;
53
+ justify-self: center;
54
+ inline-size: 2px;
55
+ block-size: 100%;
56
+ min-block-size: var(--s2);
57
+ background: var(--accent-color);
58
+ }
59
+
60
+ .velu-step__title {
61
+ grid-row: 1;
62
+ grid-column: 2;
63
+ align-self: center;
64
+ font-size: var(--f-h4);
65
+ line-height: var(--lh-h4);
66
+ font-weight: var(--weight-medium);
67
+ color: var(--text-color);
68
+ }
69
+
70
+ .velu-step__body {
71
+ grid-row: 2;
72
+ grid-column: 2;
73
+ padding-block: var(--s-1) var(--s2);
74
+ color: var(--text-color);
75
+ font-size: var(--f-body);
76
+ line-height: var(--lh-body);
77
+ }