@writedocs/generator 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 (95) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +17 -0
  3. package/astro.config.mjs +419 -0
  4. package/bin/writedocs.js +73 -0
  5. package/package.json +79 -0
  6. package/src/assets/wd_watermark.png +0 -0
  7. package/src/assets/wd_watermark_dark.png +0 -0
  8. package/src/cli/build-auth.js +53 -0
  9. package/src/cli/build.js +40 -0
  10. package/src/cli/dev.js +12 -0
  11. package/src/cli/generate-api-pages.js +359 -0
  12. package/src/cli/init.js +81 -0
  13. package/src/cli/preflight.js +40 -0
  14. package/src/cli/run-astro.js +57 -0
  15. package/src/cli/run-pagefind.js +66 -0
  16. package/src/cli/write-redirects-file.js +80 -0
  17. package/src/components/Accordion.astro +164 -0
  18. package/src/components/AccordionGroup.astro +40 -0
  19. package/src/components/ApiLangSelect.astro +168 -0
  20. package/src/components/ApiPlayground.astro +281 -0
  21. package/src/components/ApiReferencePanel.astro +1754 -0
  22. package/src/components/ApiSchemaField.astro +54 -0
  23. package/src/components/AppIcon.astro +32 -0
  24. package/src/components/Badge.astro +128 -0
  25. package/src/components/Callout.astro +168 -0
  26. package/src/components/Card.astro +136 -0
  27. package/src/components/CardGroup.astro +20 -0
  28. package/src/components/CodeGroup.astro +184 -0
  29. package/src/components/CopyPageMenu.astro +246 -0
  30. package/src/components/Danger.astro +12 -0
  31. package/src/components/Expandable.astro +126 -0
  32. package/src/components/Frame.astro +102 -0
  33. package/src/components/Hint.astro +99 -0
  34. package/src/components/Icon.astro +70 -0
  35. package/src/components/Image.astro +147 -0
  36. package/src/components/Info.astro +12 -0
  37. package/src/components/Note.astro +12 -0
  38. package/src/components/Parameter.astro +119 -0
  39. package/src/components/RequestExample.astro +33 -0
  40. package/src/components/ResponseExample.astro +19 -0
  41. package/src/components/Searchbar.astro +117 -0
  42. package/src/components/Step.astro +10 -0
  43. package/src/components/Steps.astro +32 -0
  44. package/src/components/Tab.astro +9 -0
  45. package/src/components/Tabs.astro +52 -0
  46. package/src/components/Tip.astro +12 -0
  47. package/src/components/Video.astro +135 -0
  48. package/src/components/Warning.astro +12 -0
  49. package/src/components/index.ts +48 -0
  50. package/src/content.config.ts +223 -0
  51. package/src/layout/BaseLayout.astro +750 -0
  52. package/src/layout/components/AnalyticsScripts.astro +77 -0
  53. package/src/layout/components/AskAiWidget.astro +37 -0
  54. package/src/layout/components/Breadcrumbs.astro +97 -0
  55. package/src/layout/components/ImageZoom.astro +19 -0
  56. package/src/layout/components/MobileMenu.astro +200 -0
  57. package/src/layout/components/NavTree.astro +351 -0
  58. package/src/layout/components/SearchModal.astro +42 -0
  59. package/src/layout/components/Sidebar.astro +122 -0
  60. package/src/layout/components/SiteFooter.astro +85 -0
  61. package/src/layout/components/TableOfContents.astro +117 -0
  62. package/src/layout/components/TopBar.astro +311 -0
  63. package/src/layout/styles/banner.css +44 -0
  64. package/src/layout/styles/base.css +234 -0
  65. package/src/layout/styles/dropdown.css +133 -0
  66. package/src/layout/styles/footer.css +108 -0
  67. package/src/layout/styles/image-zoom.css +50 -0
  68. package/src/layout/styles/mobile-menu.css +258 -0
  69. package/src/layout/styles/search-modal.css +122 -0
  70. package/src/layout/styles/topbar.css +437 -0
  71. package/src/lib/config.ts +2131 -0
  72. package/src/lib/mdx-auto-hydrate.js +70 -0
  73. package/src/lib/mdx-inject-builtins.js +87 -0
  74. package/src/lib/mdx-substitute-variables.js +66 -0
  75. package/src/lib/mdx-title-anchor-ids.js +84 -0
  76. package/src/lib/mermaid-rehype.js +72 -0
  77. package/src/lib/openapi-render.ts +479 -0
  78. package/src/lib/shiki-code-block.js +102 -0
  79. package/src/lib/shiki-copy-button.js +45 -0
  80. package/src/lib/styles-asset-integration.js +210 -0
  81. package/src/lib/writedocs-temp-dir.js +93 -0
  82. package/src/pages/404.astro +62 -0
  83. package/src/pages/[...slug].astro +1270 -0
  84. package/src/pages/[...slug].md.ts +78 -0
  85. package/src/pages/llms-full.txt.ts +71 -0
  86. package/src/pages/llms.txt.ts +141 -0
  87. package/src/scripts/banner.ts +20 -0
  88. package/src/scripts/dropdowns.ts +61 -0
  89. package/src/scripts/image-zoom.ts +66 -0
  90. package/src/scripts/mobile-menu.ts +55 -0
  91. package/src/scripts/search.ts +155 -0
  92. package/src/scripts/sidebar-scroll.ts +65 -0
  93. package/src/scripts/theme-toggle.ts +35 -0
  94. package/src/scripts/topbar-offset.ts +141 -0
  95. package/src/styles/global.css +18 -0
@@ -0,0 +1,437 @@
1
+ /* TopBar.astro's own styling. Also imported by MobileMenu.astro, for two
2
+ classes its own drawer header reuses verbatim: .wd-topbar-brand (the
3
+ brand link, replicated in the drawer's own header) and .wd-theme-toggle
4
+ (the drawer renders its own second copy of this button - see
5
+ src/scripts/theme-toggle.ts for why that's safe). */
6
+
7
+ .wd-topbar {
8
+ border-bottom: 1px solid var(--wd-border);
9
+ position: sticky;
10
+ top: 0;
11
+ /* --wd-navbar-background - falls back to the page's own --wd-background
12
+ when writedocs.json doesn't set theme.colors.navbar (see BaseLayout.astro),
13
+ so an unconfigured navbar keeps blending into the page as before. */
14
+ background: var(--wd-navbar-background);
15
+ z-index: 10;
16
+ }
17
+ /* Two stacked rows: brand + switchers on top, tabs/global dropdowns
18
+ underneath - only the top row is always present, the second only
19
+ renders when the writedocs.json actually has tabs or global dropdowns. */
20
+ .wd-topbar-row-brand {
21
+ /* border-bottom: 1px solid var(--wd-border); */
22
+ }
23
+ .wd-topbar-row-brand:last-child {
24
+ border-bottom: none;
25
+ }
26
+ .wd-topbar-inner {
27
+ max-width: 1440px;
28
+ margin: 0 auto;
29
+ padding: 0.75rem 0;
30
+ display: flex;
31
+ align-items: center;
32
+ gap: 1rem;
33
+ }
34
+ .wd-topbar-row-tabs .wd-topbar-inner {
35
+ padding-top: 0.4rem;
36
+ /* No bottom padding, deliberately - .wd-tab-link's own border-bottom
37
+ (below) sits flush against this row's bottom edge (the outer
38
+ .wd-topbar's own border-bottom, since this is the last row) rather
39
+ than floating partway up inside a padded gap. That's what lets a
40
+ plain border-bottom color change read as a real underline on hover,
41
+ and what makes the active tab's own fill look like it's actually
42
+ attached to the row's bottom edge instead of a floating pill. */
43
+ padding-bottom: 0;
44
+ }
45
+ .wd-topbar-brand {
46
+ display: flex;
47
+ align-items: center;
48
+ gap: 0.5rem;
49
+ font-weight: 600;
50
+ text-decoration: none;
51
+ /* --wd-navbar-foreground, not --wd-text - falls back to var(--wd-text)
52
+ when theme.navbar has no `foreground` set (see BaseLayout.astro), so
53
+ this is a no-op for the common case; only matters once a site's
54
+ navbar background is far enough from the page background that
55
+ --wd-text reads poorly against it. Also picked up by
56
+ MobileMenu.astro's own copy of this same class in its drawer header -
57
+ see this file's own top comment. */
58
+ color: var(--wd-navbar-foreground);
59
+ font-size: 1.05rem;
60
+ flex-shrink: 0;
61
+ }
62
+ /* Switchers sit right next to the brand (no auto margin here) -
63
+ .wd-topbar-links below is what gets pushed to the far right. */
64
+ .wd-topbar-switchers {
65
+ display: flex;
66
+ align-items: center;
67
+ gap: 0.4rem;
68
+ }
69
+ /* --wd-navbar-border, not --wd-border - falls back to the literal
70
+ var(--wd-border) reference when theme.navbar isn't configured (see
71
+ BaseLayout.astro), so this is a no-op for the common case. Once a
72
+ navbar background is set, though, the flat neutral --wd-border reads as
73
+ a harsh, near-white outline against it (not picked with any navbar hue
74
+ in mind) - --wd-navbar-border is a soft tint of the navbar's own
75
+ already-contrast-correct text color instead, so the pill's edge stays
76
+ legible without standing out. */
77
+ .wd-switcher-trigger {
78
+ border: 1px solid var(--wd-navbar-border);
79
+ }
80
+ /* .wd-dropdown-trigger's own base rule (dropdown.css) is deliberately
81
+ generic - it's shared by every dropdown in the codebase, including
82
+ CopyPageMenu.astro's trigger, which sits on the ordinary page
83
+ background, not the navbar's. Overriding it here, scoped to `.wd-topbar`
84
+ specifically (which every dropdown trigger this file renders - the
85
+ version/language/product switchers, a tab-as-dropdown, the small-screen
86
+ topbar.links ellipsis - actually lives inside), is what lets the topbar's
87
+ own triggers pick up --wd-navbar-foreground-muted without touching that
88
+ unrelated one. Two classes beats dropdown.css's one-class base rule on
89
+ specificity regardless of the two files' own import order, so this is
90
+ safe either way. The caret arrow inside needs no rule of its own - its
91
+ `stroke="currentColor"` already inherits whatever `color` wins here. */
92
+ .wd-topbar .wd-dropdown-trigger {
93
+ color: var(--wd-navbar-foreground);
94
+ }
95
+ .wd-topbar .wd-dropdown-trigger:hover {
96
+ color: var(--wd-navbar-foreground);
97
+ }
98
+ .wd-topbar-tabs {
99
+ display: flex;
100
+ /* stretch (not center) - every direct flex item in this row (a plain
101
+ .wd-tab-link <a>, or the .wd-dropdown <div> wrapping a tab-as-
102
+ dropdown's own trigger <button>) now spans this row's full height,
103
+ so its own border-bottom (see .wd-tab-link below) always lands
104
+ exactly on the row's bottom edge. Centering by natural content
105
+ height instead would leave a gap for a <button>-based item: browsers
106
+ give <button> a shorter default line-height than the 1.6 an <a>
107
+ inherits from <body>, and TopBar.astro doesn't override it - so an
108
+ un-stretched trigger button ends up genuinely shorter than a plain
109
+ tab, and centering it within the row leaves empty space above *and*
110
+ below it instead of flush at the bottom. Real bug this fixes, not a
111
+ hypothetical - a dropdown-as-tab's hover border-bottom used to sit
112
+ visibly above the row's own divider line instead of touching it. */
113
+ align-items: stretch;
114
+ gap: 0.25rem;
115
+ flex: 1;
116
+ flex-wrap: wrap;
117
+ }
118
+ /* .wd-dropdown itself is just a plain block (position: relative, for its
119
+ own .wd-dropdown-menu to anchor to) - stretching *it* to the row's
120
+ height (above) doesn't automatically stretch its child trigger
121
+ <button> too, since a plain block doesn't center/stretch its own
122
+ children. display: flex makes it a flex container of its own single
123
+ child - flexbox's own default align-items is already 'stretch', so
124
+ the trigger button fills it completely with no extra rule needed.
125
+ Scoped to just this row (not every .wd-dropdown site-wide - switcher
126
+ triggers and CopyPageMenu.astro also use this same class, and don't
127
+ have this row's height-flushing concern) so nothing about their own
128
+ layout changes. Applies to both a tab-as-dropdown's own wrapper and a
129
+ global-dropdown's, when either renders inside the tabs row - keeping
130
+ both consistent with each other, not just with plain tabs. */
131
+ .wd-topbar-tabs .wd-dropdown {
132
+ display: flex;
133
+ }
134
+ .wd-tab-link {
135
+ display: flex;
136
+ align-items: center;
137
+ gap: 0.4rem;
138
+ padding: 0.2rem 0.625rem;
139
+ /* Rounded top corners, square bottom - reads as an actual "tab"
140
+ attached to the row's bottom edge (see .wd-topbar-row-tabs
141
+ .wd-topbar-inner's own comment) rather than a floating pill. Same
142
+ radius for every tab, active or not, so nothing needs to change
143
+ shape on top when a tab becomes active - only the fill/border-bottom
144
+ below do. */
145
+ border-radius: 0.5rem 0.5rem 0 0;
146
+ /* Transparent by default - this is what a hover (below) or the active
147
+ state colors in, rather than a separate underline element. Sized to
148
+ land exactly on the row's own bottom edge now that this row's inner
149
+ wrapper has no bottom padding of its own. */
150
+ border-bottom: 2px solid transparent;
151
+ text-decoration: none;
152
+ color: var(--wd-navbar-foreground);
153
+ font-size: 0.92rem;
154
+ font-weight: 600;
155
+ }
156
+ /* The selected tab: a solid fill, not just a tinted background -
157
+ AppIcon's <svg> render mode already uses fill="currentColor" (astro-
158
+ icon's default), so its icon recolors along with the text; the
159
+ emoji/text <span> fallback inherits `color` the same way.
160
+ border-bottom-color matches the fill (rather than being reset to
161
+ transparent) so there's no 2px seam of the row's own background
162
+ showing between the fill and the row's bottom edge/border.
163
+ --wd-navbar-accent (falls back to --wd-primary - see BaseLayout.astro),
164
+ not a bare --wd-primary reference: without this, a site whose navbar
165
+ background *is* --wd-primary (a plausible "brand-colored navbar" choice
166
+ - the exact case that motivated this variable) would have its active
167
+ tab's own fill disappear into the row's background entirely. Text color
168
+ is --wd-navbar-accent-text (also BaseLayout.astro) rather than a
169
+ hardcoded #fff for the matching reason - a light accent color needs
170
+ dark text, not white, to stay legible on top of it. */
171
+ .wd-tab-link.active {
172
+ color: var(--wd-navbar-accent-text);
173
+ background: var(--wd-navbar-accent);
174
+ border-bottom-color: var(--wd-navbar-accent);
175
+ }
176
+ /* Inactive tabs just get their border-bottom colored in on hover -
177
+ simpler than a separate underline element, and lines up naturally
178
+ with the active tab's own border-bottom above since both are the same
179
+ property. Text/icon color deliberately stays as-is on hover (only the
180
+ border appears), matching the reference this was built against. */
181
+ .wd-tab-link:hover:not(.active) {
182
+ border-bottom-color: var(--wd-navbar-accent);
183
+ }
184
+ .wd-topbar-links {
185
+ display: flex;
186
+ gap: 1.25rem;
187
+ font-size: 0.9rem;
188
+ flex-shrink: 0;
189
+ margin-left: auto;
190
+ }
191
+ .wd-topbar-links a {
192
+ display: inline-flex;
193
+ align-items: center;
194
+ gap: 0.35rem;
195
+ text-decoration: none;
196
+ color: var(--wd-navbar-foreground-muted);
197
+ }
198
+ .wd-topbar-links a:hover {
199
+ color: var(--wd-navbar-foreground);
200
+ }
201
+ /* Hidden above 860px - .wd-topbar-links (the plain inline row) is what
202
+ shows there instead. Same margin-left: auto as that row so it lands in
203
+ the same "pushed to the far right, right before search/theme" spot once
204
+ the media query below swaps which of the two is visible. */
205
+ .wd-topbar-links-mobile {
206
+ display: none;
207
+ margin-left: auto;
208
+ flex-shrink: 0;
209
+ }
210
+ /* The extra .wd-topbar-links-mobile qualifier (2 classes) is load-bearing,
211
+ not decoration: a bare .wd-topbar-links-toggle selector would tie on
212
+ specificity with .wd-dropdown-trigger's own padding/width (dropdown.css)
213
+ - whichever of the two files happens to load/cascade later would
214
+ silently win regardless of intent, and this button needs to reliably
215
+ become a square icon button, not keep the trigger's default text-button
216
+ padding. */
217
+ .wd-topbar-links-mobile .wd-topbar-links-toggle {
218
+ width: 2rem;
219
+ height: 2rem;
220
+ justify-content: center;
221
+ padding: 0;
222
+ }
223
+ .wd-topbar-links-mobile .wd-dropdown-menu {
224
+ left: auto;
225
+ right: 0;
226
+ }
227
+
228
+ /* The topbar trigger looks like a real search box but is a <button>, not
229
+ an <input> - it never accepts text itself, clicking (or the ⌘K/Ctrl K
230
+ shortcut, see src/scripts/search.ts) opens the real .wd-search-modal
231
+ (SearchModal.astro) instead. A genuinely-typable fake input would be
232
+ confusing (why can't I select my typed text after opening the modal?)
233
+ and worse for a11y than a button that's honest about being a button. */
234
+ .wd-search-trigger {
235
+ display: flex;
236
+ align-items: center;
237
+ gap: 0.5rem;
238
+ width: 100%;
239
+ max-width: 220px;
240
+ padding: 0.4rem 0.6rem;
241
+ border: 1px solid var(--wd-border);
242
+ border-radius: 0.5rem;
243
+ background: var(--wd-surface);
244
+ /* Deliberately NOT --wd-navbar-foreground(-muted) - this box always sits
245
+ on --wd-surface (a fixed light/dark neutral), never on the navbar's
246
+ own background, so tying its text to the navbar's computed contrast
247
+ color is wrong: a navbar dark enough to need white text would make
248
+ this white-on-light-surface text unreadable (the actual bug this
249
+ replaced). --wd-text-muted instead - same var the "Ctrl K" kbd chip
250
+ inside this same trigger already uses, so both pieces of text read as
251
+ one consistent color, and it already tracks light/dark mode on its
252
+ own without a separate [data-theme="dark"] override here. */
253
+ color: var(--wd-text-muted);
254
+ font-size: 0.85rem;
255
+ font-family: inherit;
256
+ cursor: pointer;
257
+ flex-shrink: 1;
258
+ }
259
+ .wd-search-trigger:hover {
260
+ border-color: color-mix(in srgb, var(--wd-navbar-accent) 40%, var(--wd-border));
261
+ }
262
+ /* Also used (as its own copy) by SearchModal.astro's own input row - one
263
+ line, not worth a shared file over. */
264
+ .wd-search-icon {
265
+ flex-shrink: 0;
266
+ }
267
+ .wd-search-placeholder {
268
+ flex: 1;
269
+ text-align: left;
270
+ overflow: hidden;
271
+ text-overflow: ellipsis;
272
+ white-space: nowrap;
273
+ }
274
+ /* .wd-search-kbd (this trigger's "⌘K" hint) and SearchModal.astro's own
275
+ .wd-search-esc share this exact declaration block - duplicated there
276
+ rather than factored into a third shared file for six lines. */
277
+ .wd-search-kbd {
278
+ flex-shrink: 0;
279
+ font-family: inherit;
280
+ font-size: 0.7rem;
281
+ padding: 0.15rem 0.4rem;
282
+ border-radius: 0.3rem;
283
+ border: 1px solid var(--wd-border);
284
+ background: var(--wd-background);
285
+ color: var(--wd-text-muted);
286
+ }
287
+
288
+ .wd-theme-toggle {
289
+ position: relative;
290
+ display: flex;
291
+ align-items: center;
292
+ justify-content: center;
293
+ width: 2rem;
294
+ height: 2rem;
295
+ padding: 0;
296
+ border: none;
297
+ border-radius: 0.4rem;
298
+ background: none;
299
+ cursor: pointer;
300
+ color: var(--wd-navbar-foreground-muted);
301
+ flex-shrink: 0;
302
+ overflow: hidden;
303
+ }
304
+ /* Softer than a flat --wd-surface swap or a text-color change (both read
305
+ as too strong a jolt, and the color swap doesn't help legibility here
306
+ the way it does for e.g. .wd-topbar-links) - a low-opacity tint of the
307
+ navbar's own foreground, so it stays a subtle "this is hoverable" cue
308
+ against any navbar background/mode instead of a hard color flip. */
309
+ .wd-theme-toggle:hover {
310
+ background: color-mix(in srgb, var(--wd-navbar-foreground) 12%, transparent);
311
+ }
312
+ /* Both icons occupy the same spot (absolutely positioned, centered on the
313
+ button) so exactly one is ever visible - the inactive one is
314
+ faded/rotated/scaled out rather than display:none'd, which is what
315
+ gives the click a smooth crossfade instead of an instant swap.
316
+ [data-theme] is what actually drives which state is active; the
317
+ toggle's click handler (src/scripts/theme-toggle.ts) just flips that
318
+ attribute, so this transition runs automatically whenever it changes,
319
+ including via the OS-preference/localStorage choice on first load. */
320
+ .wd-theme-icon {
321
+ position: absolute;
322
+ top: 50%;
323
+ left: 50%;
324
+ width: 1.1em;
325
+ height: 1.1em;
326
+ transform: translate(-50%, -50%) rotate(0deg) scale(1);
327
+ opacity: 1;
328
+ transition:
329
+ transform 0.35s ease,
330
+ opacity 0.25s ease;
331
+ }
332
+ .wd-theme-icon-moon {
333
+ opacity: 0;
334
+ transform: translate(-50%, -50%) rotate(-90deg) scale(0.5);
335
+ }
336
+ [data-theme="dark"] .wd-theme-icon-sun {
337
+ opacity: 0;
338
+ transform: translate(-50%, -50%) rotate(90deg) scale(0.5);
339
+ }
340
+ [data-theme="dark"] .wd-theme-icon-moon {
341
+ opacity: 1;
342
+ transform: translate(-50%, -50%) rotate(0deg) scale(1);
343
+ }
344
+
345
+ /* The hamburger-turned-close button (below 860px only) that opens
346
+ MobileMenu.astro's own panel - rendered as the first child of
347
+ .wd-topbar-inner, so its styling lives here alongside the rest of the
348
+ topbar row rather than with the panel it opens. */
349
+ .wd-mobile-menu-toggle {
350
+ display: none;
351
+ position: relative;
352
+ align-items: center;
353
+ justify-content: center;
354
+ width: 2rem;
355
+ height: 2rem;
356
+ padding: 0;
357
+ border: none;
358
+ border-radius: 0.4rem;
359
+ background: none;
360
+ cursor: pointer;
361
+ color: var(--wd-navbar-foreground-muted);
362
+ flex-shrink: 0;
363
+ }
364
+ .wd-mobile-menu-toggle:hover {
365
+ color: var(--wd-navbar-foreground);
366
+ background: var(--wd-surface);
367
+ }
368
+ /* Same crossfade-two-icons-in-place technique as .wd-theme-toggle's
369
+ sun/moon above - .open (set by initMobileMenu(), src/scripts/mobile-menu.ts)
370
+ swaps which of the two is visible. */
371
+ .wd-mobile-menu-icon {
372
+ position: absolute;
373
+ top: 50%;
374
+ left: 50%;
375
+ transform: translate(-50%, -50%) rotate(0deg) scale(1);
376
+ opacity: 1;
377
+ transition:
378
+ transform 0.35s ease,
379
+ opacity 0.25s ease;
380
+ }
381
+ .wd-mobile-menu-icon-close {
382
+ opacity: 0;
383
+ transform: translate(-50%, -50%) rotate(-90deg) scale(0.5);
384
+ }
385
+ .wd-mobile-menu-toggle.open .wd-mobile-menu-icon-bars {
386
+ opacity: 0;
387
+ transform: translate(-50%, -50%) rotate(90deg) scale(0.5);
388
+ }
389
+ .wd-mobile-menu-toggle.open .wd-mobile-menu-icon-close {
390
+ opacity: 1;
391
+ transform: translate(-50%, -50%) rotate(0deg) scale(1);
392
+ }
393
+
394
+ @media (max-width: 1500px) {
395
+ .wd-topbar-inner,
396
+ .wd-shell {
397
+ padding: 0.75rem;
398
+ }
399
+ }
400
+
401
+ @media (max-width: 860px) {
402
+ .wd-search-trigger {
403
+ max-width: none;
404
+ order: 1;
405
+ flex-basis: 100%;
406
+ }
407
+ }
408
+ @media (max-width: 860px) {
409
+ .wd-topbar-inner {
410
+ flex-wrap: wrap;
411
+ gap: 0.75rem;
412
+ }
413
+ /* Both move into MobileMenu.astro's own panel instead - version/
414
+ language/product/nested-dropdown switchers as one accordion row each,
415
+ the tabs bar and global dropdowns alongside them, all reusing the
416
+ same `selectors`/`globalDropdowns` props this row already renders
417
+ from. */
418
+ .wd-topbar-switchers {
419
+ display: none;
420
+ }
421
+ .wd-topbar-row-tabs {
422
+ display: none;
423
+ }
424
+ /* The inline link row would otherwise wrap onto its own line next to
425
+ the brand/theme controls, eating vertical space - collapsed behind
426
+ the single ellipsis button (.wd-topbar-links-mobile) instead, which
427
+ reuses the existing dropdown mechanism. */
428
+ .wd-topbar-links {
429
+ display: none;
430
+ }
431
+ .wd-topbar-links-mobile {
432
+ display: block;
433
+ }
434
+ .wd-mobile-menu-toggle {
435
+ display: flex;
436
+ }
437
+ }