@veluai/velu 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/dist/cli.js +11 -0
  2. package/package.json +52 -0
  3. package/runtime/velu-ui/base.css +311 -0
  4. package/runtime/velu-ui/components/Accordion.jsx +64 -0
  5. package/runtime/velu-ui/components/ApiClient.jsx +121 -0
  6. package/runtime/velu-ui/components/ApiField.jsx +87 -0
  7. package/runtime/velu-ui/components/ApiPath.jsx +63 -0
  8. package/runtime/velu-ui/components/ApiSidebar.jsx +122 -0
  9. package/runtime/velu-ui/components/AskBar.jsx +71 -0
  10. package/runtime/velu-ui/components/Callout.jsx +114 -0
  11. package/runtime/velu-ui/components/Card.jsx +131 -0
  12. package/runtime/velu-ui/components/Chatbot.jsx +596 -0
  13. package/runtime/velu-ui/components/CodeBlock.jsx +375 -0
  14. package/runtime/velu-ui/components/Columns.jsx +56 -0
  15. package/runtime/velu-ui/components/Field.jsx +81 -0
  16. package/runtime/velu-ui/components/Image.jsx +163 -0
  17. package/runtime/velu-ui/components/MethodBadge.jsx +31 -0
  18. package/runtime/velu-ui/components/NavSelect.jsx +108 -0
  19. package/runtime/velu-ui/components/PageFeedback.jsx +219 -0
  20. package/runtime/velu-ui/components/PageFooter.jsx +213 -0
  21. package/runtime/velu-ui/components/PageHeader.jsx +414 -0
  22. package/runtime/velu-ui/components/PageNav.jsx +77 -0
  23. package/runtime/velu-ui/components/PoweredBy.jsx +51 -0
  24. package/runtime/velu-ui/components/Prompt.jsx +115 -0
  25. package/runtime/velu-ui/components/Search.jsx +366 -0
  26. package/runtime/velu-ui/components/Sidebar.jsx +191 -0
  27. package/runtime/velu-ui/components/Steps.jsx +65 -0
  28. package/runtime/velu-ui/components/ThemeToggle.jsx +48 -0
  29. package/runtime/velu-ui/components/Toc.jsx +537 -0
  30. package/runtime/velu-ui/components/TocBar.jsx +195 -0
  31. package/runtime/velu-ui/components/Tree.jsx +87 -0
  32. package/runtime/velu-ui/components/TryItBar.jsx +90 -0
  33. package/runtime/velu-ui/components/accordion.css +92 -0
  34. package/runtime/velu-ui/components/api.css +479 -0
  35. package/runtime/velu-ui/components/ask-bar.css +94 -0
  36. package/runtime/velu-ui/components/card.css +105 -0
  37. package/runtime/velu-ui/components/chatbot.css +617 -0
  38. package/runtime/velu-ui/components/code-block.css +263 -0
  39. package/runtime/velu-ui/components/docs-layout.css +775 -0
  40. package/runtime/velu-ui/components/field.css +82 -0
  41. package/runtime/velu-ui/components/image.css +237 -0
  42. package/runtime/velu-ui/components/nav-select.css +157 -0
  43. package/runtime/velu-ui/components/page-feedback.css +241 -0
  44. package/runtime/velu-ui/components/page-footer.css +130 -0
  45. package/runtime/velu-ui/components/page-header.css +520 -0
  46. package/runtime/velu-ui/components/page-nav.css +50 -0
  47. package/runtime/velu-ui/components/powered-by.css +66 -0
  48. package/runtime/velu-ui/components/prompt.css +99 -0
  49. package/runtime/velu-ui/components/search.css +307 -0
  50. package/runtime/velu-ui/components/sidebar.css +144 -0
  51. package/runtime/velu-ui/components/steps.css +77 -0
  52. package/runtime/velu-ui/components/theme-toggle.css +70 -0
  53. package/runtime/velu-ui/components/toc-bar.css +234 -0
  54. package/runtime/velu-ui/components/tree.css +49 -0
  55. package/runtime/velu-ui/index.js +45 -0
  56. package/runtime/velu-ui/lib/copyText.js +64 -0
  57. package/runtime/velu-ui/lib/lang-icons.jsx +156 -0
  58. package/runtime/velu-ui/lib/prism-langs.js +957 -0
  59. package/runtime/velu-ui/lib/prism-loader.js +74 -0
  60. package/runtime/velu-ui/lib/resolveIcon.jsx +29 -0
  61. package/runtime/velu-ui/lib/scrollIntoNearestView.js +66 -0
  62. package/runtime/velu-ui/mdx-components.jsx +85 -0
  63. package/runtime/velu-ui/primitives/Cluster.jsx +49 -0
  64. package/runtime/velu-ui/primitives/Stack.jsx +63 -0
  65. package/runtime/velu-ui/primitives/Switcher.jsx +57 -0
  66. package/runtime/velu-ui/primitives/stack.css +3 -0
  67. package/runtime/velu-ui/primitives/switcher.css +25 -0
  68. package/runtime/velu-ui/styles.css +43 -0
  69. package/runtime/velu-ui/tokens.css +4 -0
  70. package/schema/velu.schema.json +167 -0
  71. package/src/navigation.js +434 -0
  72. package/src/runtime/App.jsx +1473 -0
  73. package/src/runtime/client-entry.jsx +22 -0
  74. package/src/runtime/server-entry.jsx +16 -0
  75. package/src/template.html +48 -0
  76. package/templates/starter/ai-tools/claude-code.mdx +26 -0
  77. package/templates/starter/ai-tools/cursor.mdx +17 -0
  78. package/templates/starter/api-reference/endpoint/create.mdx +24 -0
  79. package/templates/starter/api-reference/endpoint/get.mdx +27 -0
  80. package/templates/starter/api-reference/introduction.mdx +28 -0
  81. package/templates/starter/development.mdx +19 -0
  82. package/templates/starter/essentials/code.mdx +28 -0
  83. package/templates/starter/essentials/images.mdx +29 -0
  84. package/templates/starter/essentials/markdown.mdx +25 -0
  85. package/templates/starter/essentials/navigation.mdx +39 -0
  86. package/templates/starter/essentials/settings.mdx +30 -0
  87. package/templates/starter/favicon.svg +6 -0
  88. package/templates/starter/index.mdx +31 -0
  89. package/templates/starter/quickstart.mdx +31 -0
  90. package/templates/starter/velu.json +33 -0
@@ -0,0 +1,82 @@
1
+ /* Field — parameter docs row. All values are tokens; light/dark via
2
+ [data-theme]. The chip / pill recipes are kept simple so they read
3
+ identically against both `--surface-color` and `--page-bg`. */
4
+
5
+ .velu-field {
6
+ display: block;
7
+ }
8
+
9
+ /* Header row of chips + name + type + required + default + post.
10
+ flex-wrap so a long set of badges falls cleanly onto a second line
11
+ on narrow widths. Items align on text baseline so the bold `name`
12
+ never visually shifts when chips have different padding. */
13
+ /* The chip row layout lives in <Cluster> now (primitives/Cluster.jsx) —
14
+ no .velu-field__head selector needed. */
15
+
16
+ /* Generic chip — used for pre / type / post. Hugs the line-height
17
+ vertically (zero block padding) with 8px / --s-3 horizontal padding;
18
+ reads as a tiny code-like badge. */
19
+ .velu-field__chip {
20
+ display: inline-flex;
21
+ align-items: center;
22
+ padding-block: 0;
23
+ padding-inline: var(--s-3);
24
+ background: var(--surface-color);
25
+ border-radius: var(--radius-sm);
26
+ font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
27
+ font-size: var(--f-h6);
28
+ line-height: var(--lh-h6);
29
+ color: var(--muted-color);
30
+ }
31
+
32
+ /* The parameter name — accent, medium weight, slightly larger than the
33
+ chips so it reads as the row's primary token. */
34
+ .velu-field__name {
35
+ font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
36
+ font-size: var(--f-h5);
37
+ line-height: var(--lh-h5);
38
+ font-weight: var(--weight-medium);
39
+ color: var(--accent-color);
40
+ }
41
+
42
+ /* Required pill — accent-tinted background + accent text. Same hugging
43
+ line-height as the generic chip. */
44
+ .velu-field__required {
45
+ display: inline-flex;
46
+ align-items: center;
47
+ padding-block: 0;
48
+ padding-inline: var(--s-3);
49
+ background: color-mix(in srgb, var(--accent-color) 18%, transparent);
50
+ border-radius: var(--radius-sm);
51
+ font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
52
+ font-size: var(--f-h6);
53
+ line-height: var(--lh-h6);
54
+ color: var(--accent-color);
55
+ }
56
+
57
+ /* default: VALUE — light italic Google Sans Code, regular text color
58
+ (not muted). */
59
+ .velu-field__default {
60
+ font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
61
+ font-style: italic;
62
+ font-weight: var(--weight-light);
63
+ font-size: var(--f-h6);
64
+ line-height: var(--lh-h6);
65
+ color: var(--text-color);
66
+ }
67
+
68
+ /* Description block beneath the chip row. */
69
+ .velu-field__body {
70
+ margin-block-start: var(--s-1);
71
+ color: var(--text-color);
72
+ font-size: var(--f-body);
73
+ line-height: var(--lh-body);
74
+ }
75
+
76
+ /* Sibling separator — drop two <Field> next to each other and the
77
+ hairline divider appears between them. No wrapper component needed. */
78
+ .velu-field + .velu-field {
79
+ margin-block-start: var(--s2);
80
+ padding-block-start: var(--s2);
81
+ border-block-start: var(--border-width) solid var(--border-color);
82
+ }
@@ -0,0 +1,237 @@
1
+ /* Image — plain / captioned / window-chrome / device-frame variants.
2
+ Tokenized; light/dark via [data-theme]. The window + frame variants share
3
+ an accent-glow + noise backdrop, plus the liquid-glass layered surface
4
+ (effect/tint/shine/content) for chrome bar + device bezel — SVG
5
+ feTurbulence→feDisplacementMap provides the actual refraction. */
6
+
7
+ .velu-image {
8
+ display: block;
9
+ margin: 0; /* reset <figure> default margin */
10
+ }
11
+ /* Chrome variants: figure hugs the contained card so the caption
12
+ naturally centers under it instead of under the full content column. */
13
+ .velu-image--chrome {
14
+ inline-size: fit-content;
15
+ margin-inline: auto;
16
+ }
17
+
18
+ .velu-image__img {
19
+ display: block;
20
+ inline-size: 100%;
21
+ block-size: auto;
22
+ border-radius: var(--radius-md);
23
+ object-fit: cover;
24
+ }
25
+ .velu-image__img--flush {
26
+ border-radius: 0;
27
+ }
28
+
29
+ .velu-image__caption {
30
+ margin-block-start: var(--s-1);
31
+ text-align: center;
32
+ font-size: var(--f-h6);
33
+ line-height: var(--lh-h6);
34
+ color: var(--muted-color);
35
+ }
36
+
37
+ /* ── Accent glow + noise grain (shared by window + frame) ────────────────── */
38
+ /* Big soft blob peeking from outside the container. The position uses
39
+ negative insets so the blob's center is outside; overflow:hidden on
40
+ the parent clips it to a quarter visible. */
41
+ .velu-image__glow {
42
+ position: absolute;
43
+ inset-block-start: calc(var(--s4) * -1);
44
+ inset-inline-start: calc(var(--s4) * -1);
45
+ inline-size: calc(var(--s5) * 5);
46
+ block-size: calc(var(--s5) * 5);
47
+ background: var(--accent-color);
48
+ border-radius: 50%;
49
+ filter: blur(var(--s3));
50
+ opacity: 0.95;
51
+ pointer-events: none;
52
+ z-index: 0;
53
+ }
54
+ .velu-image__noise {
55
+ position: absolute;
56
+ inset: 0;
57
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
58
+ opacity: 0.6;
59
+ mix-blend-mode: overlay;
60
+ pointer-events: none;
61
+ z-index: 0;
62
+ }
63
+
64
+ /* ── Liquid-glass surface (lucasromerodb pattern) ────────────────────────── */
65
+ /* Four-layer stack: effect (backdrop-blur + SVG displacement filter),
66
+ tint (translucent white), shine (inset highlights), content (children).
67
+ Stays usable across themes — tint+shine are universal optical constants
68
+ (white), not palette tokens. */
69
+ .velu-glass {
70
+ position: relative;
71
+ display: flex;
72
+ /* No overflow:hidden — each inner layer rounds itself via
73
+ `border-radius: inherit`, so we don't need to clip at the parent.
74
+ Skipping the clip lets children's box-shadows (e.g. the raised
75
+ screen inside the bezel) extend outside the glass surface. */
76
+ box-shadow:
77
+ 0 var(--s-1) var(--s-1) color-mix(in srgb, #000 20%, transparent),
78
+ 0 0 var(--s1) color-mix(in srgb, #000 10%, transparent);
79
+ }
80
+ /* Each layer rounds itself rather than relying on parent overflow:hidden —
81
+ Chrome doesn't reliably clip backdrop-filter / inset-box-shadow to a
82
+ rounded parent, which produces 90° corners poking through curves. */
83
+ .velu-glass__effect,
84
+ .velu-glass__tint,
85
+ .velu-glass__shine,
86
+ .velu-glass__content {
87
+ border-radius: inherit;
88
+ }
89
+ /* Displacement must be applied to the BACKDROP (what's behind the element),
90
+ not to the element itself. `filter: url()` would apply to the (empty)
91
+ effect div; `backdrop-filter: url()` refracts the actual backdrop.
92
+ Chromium-only; Safari/Firefox fall back to plain blur. */
93
+ .velu-glass__effect {
94
+ position: absolute;
95
+ inset: 0;
96
+ z-index: 0;
97
+ -webkit-backdrop-filter: blur(3px) url(#velu-glass-distortion);
98
+ backdrop-filter: blur(3px) url(#velu-glass-distortion);
99
+ isolation: isolate;
100
+ }
101
+ .velu-glass__tint {
102
+ position: absolute;
103
+ inset: 0;
104
+ z-index: 1;
105
+ background: rgba(255, 255, 255, 0.25);
106
+ }
107
+ .velu-glass__shine {
108
+ position: absolute;
109
+ inset: 0;
110
+ z-index: 2;
111
+ box-shadow:
112
+ inset 2px 2px 1px 0 rgba(255, 255, 255, 0.5),
113
+ inset -1px -1px 1px 1px rgba(255, 255, 255, 0.5);
114
+ }
115
+ .velu-glass__content {
116
+ position: relative;
117
+ z-index: 3;
118
+ inline-size: 100%;
119
+ }
120
+
121
+ /* ── Window-chrome variant ──────────────────────────────────────────────── */
122
+ /* Outer = grey card. Nested radii are properly concentric:
123
+ outer_radius ▸ surface_radius (= outer - outer_padding) ▸
124
+ inner_radius (= surface - surface_padding). Padding is kept small
125
+ enough that every level's curve stays positive. */
126
+ .velu-image__window {
127
+ position: relative;
128
+ padding: var(--s-1);
129
+ border-radius: var(--radius-lg);
130
+ overflow: hidden;
131
+ background: var(--surface-color);
132
+ max-inline-size: 36rem;
133
+ margin-inline: auto;
134
+ }
135
+ /* Glass surface (tray) that the chrome+image card sits on. Peeks out
136
+ around the inner card as a visible glass border.
137
+ radius = outer_radius - outer_padding (concentric with outer card). */
138
+ .velu-image__window-surface {
139
+ position: relative;
140
+ z-index: 1;
141
+ inline-size: 100%;
142
+ border-radius: calc(var(--radius-lg) - var(--s-1));
143
+ }
144
+ .velu-image__window-surface > .velu-glass__content {
145
+ padding: var(--s-2);
146
+ }
147
+ /* Inner card holds the chrome bar + image.
148
+ radius = surface_radius - surface_padding (concentric with surface).
149
+ A soft drop-shadow lifts it off the glass tray. */
150
+ .velu-image__window-inner {
151
+ position: relative;
152
+ inline-size: 100%;
153
+ border-radius: calc(var(--radius-lg) - var(--s-1) - var(--s-2));
154
+ overflow: hidden;
155
+ box-shadow:
156
+ 0 var(--s-2) var(--s-1) color-mix(in srgb, #000 18%, transparent),
157
+ 0 var(--s-4) var(--s-3) color-mix(in srgb, #000 12%, transparent);
158
+ }
159
+ /* Chrome bar sits ABOVE the image (in flow, no overlap). The image
160
+ renders below it. Chrome is glass-styled via the Glass wrapper.
161
+ Top corners match the window's radius; bottom stays flat where it
162
+ meets the image. Inner glass layers inherit via `border-radius:
163
+ inherit`. */
164
+ .velu-image__chrome {
165
+ border-start-start-radius: calc(var(--radius-lg) - var(--s-1) - var(--s-2));
166
+ border-start-end-radius: calc(var(--radius-lg) - var(--s-1) - var(--s-2));
167
+ /* The default `.velu-glass` drop-shadow casts a dark line onto the
168
+ image below — undesired here since the chrome meets the image
169
+ directly. The bezel keeps its shadow because it sits in a padded
170
+ grey card that absorbs it. */
171
+ box-shadow: none;
172
+ }
173
+ .velu-image__chrome > .velu-glass__content {
174
+ display: flex;
175
+ align-items: center;
176
+ gap: var(--s-1);
177
+ padding: var(--s-1);
178
+ }
179
+ .velu-image__dots {
180
+ display: inline-flex;
181
+ gap: var(--s-3);
182
+ padding-inline: var(--s-3);
183
+ }
184
+ .velu-image__dot {
185
+ inline-size: 0.75em;
186
+ block-size: 0.75em;
187
+ border-radius: 50%;
188
+ }
189
+ .velu-image__dot--red { background: #ff5f57; }
190
+ .velu-image__dot--yellow { background: #febc2e; }
191
+ .velu-image__dot--green { background: #28c840; }
192
+ /* URL bar is absolutely centered in the chrome regardless of the dots'
193
+ width on the left — the .velu-glass__content already has
194
+ position: relative, so this anchors to that. */
195
+ .velu-image__urlbar {
196
+ position: absolute;
197
+ inset-inline-start: 50%;
198
+ transform: translateX(-50%);
199
+ inline-size: 15%;
200
+ block-size: 0.5em;
201
+ border-radius: 999px;
202
+ background: color-mix(in srgb, var(--text-color) 14%, transparent);
203
+ }
204
+
205
+ /* ── Device-frame variant ───────────────────────────────────────────────── */
206
+ /* Outer = grey card. Concentric nesting: outer → bezel → screen, each
207
+ radius = parent_radius - padding so all corner curves align. */
208
+ .velu-image__frame {
209
+ position: relative;
210
+ display: flex;
211
+ justify-content: center;
212
+ padding: var(--s-1);
213
+ border-radius: var(--radius-lg);
214
+ overflow: hidden;
215
+ background: var(--surface-color);
216
+ max-inline-size: 18rem;
217
+ margin-inline: auto;
218
+ }
219
+ /* Bezel: concentric with outer card. */
220
+ .velu-image__frame-bezel {
221
+ position: relative;
222
+ z-index: 1;
223
+ inline-size: 13rem;
224
+ max-inline-size: 100%;
225
+ border-radius: calc(var(--radius-lg) - var(--s-1));
226
+ }
227
+ .velu-image__frame-bezel > .velu-glass__content {
228
+ padding: var(--s-2);
229
+ }
230
+ /* Screen: concentric with bezel. Soft drop-shadow lifts it off the bezel. */
231
+ .velu-image__frame-screen {
232
+ border-radius: calc(var(--radius-lg) - var(--s-1) - var(--s-2));
233
+ overflow: hidden;
234
+ box-shadow:
235
+ 0 var(--s-2) var(--s-1) color-mix(in srgb, #000 18%, transparent),
236
+ 0 var(--s-4) var(--s-3) color-mix(in srgb, #000 12%, transparent);
237
+ }
@@ -0,0 +1,157 @@
1
+ /* NavSelect — dropdown switcher for product / version / language.
2
+ Shares the visual recipe with the docs drawer's doc-select. All
3
+ values are tokens; light/dark via [data-theme]. */
4
+
5
+ .velu-nav-select {
6
+ position: relative;
7
+ display: inline-block;
8
+ }
9
+
10
+ .velu-nav-select__btn {
11
+ display: inline-flex;
12
+ align-items: center;
13
+ gap: var(--s-3);
14
+ inline-size: 100%;
15
+ padding-block: var(--s-3);
16
+ padding-inline: var(--s0);
17
+ background: var(--page-bg);
18
+ border: var(--border-width) solid var(--border-color);
19
+ border-radius: var(--radius-sm);
20
+ font: inherit;
21
+ font-size: var(--f-h5);
22
+ color: var(--text-color);
23
+ text-align: start;
24
+ cursor: pointer;
25
+ transition: border-color 0.12s ease;
26
+ }
27
+ .velu-nav-select__btn:hover {
28
+ border-color: var(--accent-color);
29
+ }
30
+
31
+ /* Bare variant — borderless text trigger (e.g. the language switcher
32
+ at the header's bottom-right, GitBook-style). */
33
+ .velu-nav-select--bare .velu-nav-select__btn {
34
+ inline-size: auto;
35
+ padding-inline: 0;
36
+ background: transparent;
37
+ border: 0;
38
+ font-size: var(--f-h6);
39
+ }
40
+ .velu-nav-select--bare .velu-nav-select__btn:hover {
41
+ color: var(--accent-color);
42
+ }
43
+
44
+ /* Language (or other) code shown uppercase before the name. Kept at
45
+ text color (not muted) — distinguished by case + size, not grey. */
46
+ .velu-nav-select__code {
47
+ flex: none;
48
+ color: var(--text-color);
49
+ text-transform: uppercase;
50
+ font-size: 0.85em;
51
+ letter-spacing: 0.02em;
52
+ }
53
+
54
+ /* Compact variant — the version pill sitting next to the brand. */
55
+ .velu-nav-select--sm .velu-nav-select__btn {
56
+ padding-block: var(--s-5);
57
+ padding-inline: var(--s-2);
58
+ font-size: var(--f-h6);
59
+ }
60
+
61
+ .velu-nav-select__btn-icon {
62
+ display: inline-flex;
63
+ flex: none;
64
+ color: var(--text-color);
65
+ }
66
+ .velu-nav-select__value {
67
+ flex: 1;
68
+ min-inline-size: 0;
69
+ overflow: hidden;
70
+ text-overflow: ellipsis;
71
+ white-space: nowrap;
72
+ }
73
+ .velu-nav-select__chev {
74
+ flex: none;
75
+ inline-size: 1em;
76
+ block-size: 1em;
77
+ stroke-width: 1;
78
+ color: var(--text-color);
79
+ transition: transform 0.18s ease;
80
+ }
81
+ .velu-nav-select[data-open='true'] .velu-nav-select__chev {
82
+ transform: rotate(180deg);
83
+ }
84
+
85
+ /* Menu — anchored below the button, fades + slides in. Always in DOM
86
+ so the transition runs both directions; visibility delayed so the
87
+ closed menu isn't focusable. */
88
+ .velu-nav-select__menu {
89
+ position: absolute;
90
+ inset-block-start: calc(100% + var(--s-3));
91
+ inset-inline-start: 0;
92
+ min-inline-size: 100%;
93
+ margin: 0;
94
+ padding-block: var(--s-2);
95
+ padding-inline: 0;
96
+ list-style: none;
97
+ background: var(--page-bg);
98
+ border: var(--border-width) solid var(--border-color);
99
+ border-radius: var(--radius-sm);
100
+ box-shadow: 0 var(--s-2) var(--s1)
101
+ color-mix(in srgb, #000 12%, transparent);
102
+ opacity: 0;
103
+ visibility: hidden;
104
+ transform: translateY(-0.25rem);
105
+ pointer-events: none;
106
+ transition:
107
+ opacity 0.15s ease,
108
+ transform 0.15s ease,
109
+ visibility 0s linear 0.15s;
110
+ z-index: 40;
111
+ }
112
+ .velu-nav-select[data-open='true'] .velu-nav-select__menu {
113
+ opacity: 1;
114
+ visibility: visible;
115
+ transform: translateY(0);
116
+ pointer-events: auto;
117
+ transition:
118
+ opacity 0.15s ease,
119
+ transform 0.15s ease,
120
+ visibility 0s;
121
+ }
122
+ /* Right-align the menu when the trigger sits at the trailing edge
123
+ (e.g. the language switcher at the header's bottom-right). */
124
+ .velu-nav-select--align-end .velu-nav-select__menu {
125
+ inset-inline-start: auto;
126
+ inset-inline-end: 0;
127
+ }
128
+
129
+ .velu-nav-select__item {
130
+ display: flex;
131
+ align-items: center;
132
+ gap: var(--s-3);
133
+ padding-block: var(--s-2);
134
+ padding-inline: var(--s0);
135
+ font-size: var(--f-h5);
136
+ color: var(--text-color);
137
+ text-decoration: none;
138
+ white-space: nowrap;
139
+ cursor: pointer;
140
+ transition: background 0.12s ease, color 0.12s ease;
141
+ }
142
+ .velu-nav-select__item:hover {
143
+ background: var(--surface-color);
144
+ color: var(--accent-color);
145
+ }
146
+ .velu-nav-select__item--active {
147
+ color: var(--accent-color);
148
+ }
149
+ .velu-nav-select__item-icon {
150
+ display: inline-flex;
151
+ flex: none;
152
+ color: var(--text-color);
153
+ }
154
+ .velu-nav-select__item:hover .velu-nav-select__item-icon,
155
+ .velu-nav-select__item--active .velu-nav-select__item-icon {
156
+ color: var(--accent-color);
157
+ }