deepspace 0.19.3 → 0.19.5

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.
@@ -1,5 +1,5 @@
1
- import { D as DocumentationRuntimeData, a as DocumentationPageComponent, b as DocumentationSiteComponent } from './public-BtArwbVM.js';
2
- export { A as Accordion, c as AccordionGroup, C as Card, d as CodeGroup, e as DefaultDocumentation, f as DocumentationApp, g as DocumentationAppProps, h as DocumentationContent, i as DocumentationSiteProps, I as Info, N as Note, S as Step, j as Steps, T as Tab, k as Tabs, l as Tip, W as Warning } from './public-BtArwbVM.js';
1
+ import { D as DocumentationRuntimeData, a as DocumentationPageComponent, b as DocumentationSiteComponent } from './public-CFAj1hL2.js';
2
+ export { A as Accordion, c as AccordionGroup, C as Card, d as CodeGroup, e as DefaultDocumentation, f as DocumentationApp, g as DocumentationAppProps, h as DocumentationContent, i as DocumentationSiteProps, I as Info, N as Note, S as Step, j as Steps, T as Tab, k as Tabs, l as Tip, W as Warning } from './public-CFAj1hL2.js';
3
3
  import 'react';
4
4
 
5
5
  declare function renderDocumentation({ data, Page, Site, }: {
@@ -14,7 +14,7 @@ import {
14
14
  Tabs,
15
15
  Tip,
16
16
  Warning
17
- } from "./chunk-233GQU2H.js";
17
+ } from "./chunk-A7UFIOWO.js";
18
18
 
19
19
  // src/documentation/runtime/server.tsx
20
20
  import { createElement } from "react";
@@ -14,6 +14,7 @@ interface DocumentationFontConfig {
14
14
  interface DocumentationThemeConfig {
15
15
  preset?: string;
16
16
  accent?: string;
17
+ accentDark?: string;
17
18
  background?: string;
18
19
  backgroundDark?: string;
19
20
  backgroundDecoration?: 'none' | 'gradient' | 'grid';
@@ -308,7 +309,6 @@ declare function parseFrontmatter(source: string, file: string): {
308
309
  frontmatter: DocumentationFrontmatter;
309
310
  body: string;
310
311
  };
311
-
312
312
  declare function htmlToText(html: string): string;
313
313
 
314
314
  declare const AGENT_SKILLS_SCHEMA = "https://schemas.agentskills.io/discovery/0.2.0/schema.json";
@@ -374,7 +374,9 @@ function parseCodeFenceInfo(value) {
374
374
  const language = raw.split(/\s+/, 1)[0]?.toLowerCase();
375
375
  const metadata = raw.slice(language?.length ?? 0).trim();
376
376
  const quotedTitle = metadata.match(/(?:^|\s)title=(?:"([^"]+)"|'([^']+)')/i);
377
- const title = quotedTitle?.[1] ?? quotedTitle?.[2] ?? (metadata && !metadata.includes("=") ? metadata : void 0);
377
+ const optionKeyword = /^(?:wrap|expandable|twoslash|focus)$/i.test(metadata);
378
+ const bareTitle = metadata && !metadata.includes("=") && !metadata.startsWith("{") && !optionKeyword ? metadata : void 0;
379
+ const title = quotedTitle?.[1] ?? quotedTitle?.[2] ?? bareTitle;
378
380
  return {
379
381
  ...language ? { language } : {},
380
382
  ...title ? { title: title.trim() } : {}
@@ -889,6 +891,7 @@ var openapiItemSchema = z.union([
889
891
  var themeObjectSchema = z.object({
890
892
  preset: z.string().trim().min(1).optional(),
891
893
  accent: z.string().trim().optional(),
894
+ accentDark: z.string().trim().optional(),
892
895
  background: z.string().trim().optional(),
893
896
  logo: z.string().trim().optional(),
894
897
  logoDark: z.string().trim().optional(),
@@ -919,8 +922,7 @@ var navigationRootSchema = z.union([
919
922
  group: z.string().trim().min(1),
920
923
  pages: z.array(navigationSchema).min(1)
921
924
  })
922
- ),
923
- global: z.record(z.string(), z.unknown()).optional()
925
+ )
924
926
  })
925
927
  ]);
926
928
  var navbarSchema = z.object({
@@ -1231,6 +1233,8 @@ function loadDocumentationConfig(appDir) {
1231
1233
  theme: {
1232
1234
  ...themeInput,
1233
1235
  accent: themeInput.accent ?? data.colors?.primary ?? data.colors?.light ?? data.colors?.dark,
1236
+ // Mintlify's colors.light is "the anchor color used in dark mode".
1237
+ accentDark: themeInput.accentDark ?? data.colors?.light,
1234
1238
  background: background?.light ?? themeInput.background,
1235
1239
  backgroundDark: background && "dark" in background ? background.dark : void 0,
1236
1240
  backgroundDecoration: data.background?.decoration,
@@ -1423,13 +1427,16 @@ function addRuntimeMetadata() {
1423
1427
  };
1424
1428
  }
1425
1429
  if (node.type === "code" && typeof node.meta === "string" && node.meta.trim()) {
1426
- node.data = {
1427
- ...node.data,
1428
- hProperties: {
1429
- ...asRecord(node.data?.hProperties),
1430
- "data-code-title": node.meta.trim()
1431
- }
1432
- };
1430
+ const { title } = parseCodeFenceInfo(`${node.lang ?? ""} ${node.meta}`.trim());
1431
+ if (title) {
1432
+ node.data = {
1433
+ ...node.data,
1434
+ hProperties: {
1435
+ ...asRecord(node.data?.hProperties),
1436
+ "data-code-title": title
1437
+ }
1438
+ };
1439
+ }
1433
1440
  }
1434
1441
  });
1435
1442
  };
@@ -3051,8 +3058,16 @@ function loadDefaultRenderer() {
3051
3058
  // src/documentation/runtime/styles/base.ts
3052
3059
  var DOCUMENTATION_BASE_CSS = String.raw`
3053
3060
  :root {
3054
- --documentation-accent: #635bff;
3055
- --documentation-accent-2: #24c8ff;
3061
+ /* The configured accent is injected as --documentation-accent-light; the
3062
+ * dark theme swaps in --documentation-accent-dark, which defaults to a
3063
+ * readable lightened derivative so a site that configures only one accent
3064
+ * never ships invisible links on the dark background. */
3065
+ --documentation-accent-light: #635bff;
3066
+ --documentation-accent-dark: color-mix(in oklab, var(--documentation-accent-light) 52%, white);
3067
+ --documentation-accent: var(--documentation-accent-light);
3068
+ /* Glyphs painted directly on the accent. Dark lightens the accent, so the
3069
+ * readable ink on it flips from white to near-black. */
3070
+ --documentation-accent-contrast: #ffffff;
3056
3071
  --documentation-brand-bg: #f8fafc;
3057
3072
  --documentation-brand-bg-dark: #0c0e14;
3058
3073
  --documentation-font-body: Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
@@ -3074,6 +3089,14 @@ var DOCUMENTATION_BASE_CSS = String.raw`
3074
3089
  --documentation-code-text: #e8ebf5;
3075
3090
  --documentation-shadow-sm: 0 1px 2px rgba(15, 18, 28, .04), 0 2px 8px rgba(15, 18, 28, .03);
3076
3091
  --documentation-shadow-lg: 0 24px 80px rgba(15, 18, 28, .18), 0 6px 24px rgba(15, 18, 28, .08);
3092
+ /* Honest glass: used only where content physically passes beneath a surface
3093
+ * (the launcher pill, the floating/mobile assistant panel). High-opacity
3094
+ * tint plus blur keeps the surface legible over prose, dark code, and
3095
+ * images without any protective gradient; the inset highlight is the lit
3096
+ * top edge that makes the pane read as material rather than mist. */
3097
+ --documentation-glass-bg: color-mix(in srgb, var(--documentation-surface-raised) 86%, transparent);
3098
+ --documentation-glass-border: color-mix(in srgb, var(--documentation-border-strong) 90%, var(--documentation-accent));
3099
+ --documentation-glass-highlight: rgba(255, 255, 255, .6);
3077
3100
  --documentation-header-height: 66px;
3078
3101
  --documentation-sidebar-width: 292px;
3079
3102
  --documentation-assistant-width: 420px;
@@ -3084,6 +3107,8 @@ var DOCUMENTATION_BASE_CSS = String.raw`
3084
3107
  }
3085
3108
 
3086
3109
  :root[data-theme="dark"] {
3110
+ --documentation-accent: var(--documentation-accent-dark);
3111
+ --documentation-accent-contrast: #0c0e14;
3087
3112
  --documentation-brand-bg: var(--documentation-brand-bg-dark);
3088
3113
  --documentation-bg: var(--documentation-brand-bg-dark);
3089
3114
  --documentation-surface: #10131b;
@@ -3101,6 +3126,9 @@ var DOCUMENTATION_BASE_CSS = String.raw`
3101
3126
  --documentation-code-text: #eef0f7;
3102
3127
  --documentation-shadow-sm: 0 1px 2px rgba(0, 0, 0, .24);
3103
3128
  --documentation-shadow-lg: 0 28px 90px rgba(0, 0, 0, .55), 0 8px 24px rgba(0, 0, 0, .35);
3129
+ --documentation-glass-bg: color-mix(in srgb, var(--documentation-surface-raised) 80%, transparent);
3130
+ --documentation-glass-border: color-mix(in srgb, var(--documentation-border-strong) 86%, var(--documentation-accent));
3131
+ --documentation-glass-highlight: rgba(255, 255, 255, .07);
3104
3132
  --documentation-focus-ring: color-mix(in srgb, var(--documentation-accent) 74%, white);
3105
3133
  color-scheme: dark;
3106
3134
  }
@@ -3112,23 +3140,24 @@ body { margin: 0; background: var(--documentation-brand-bg); color: var(--docume
3112
3140
  :root[data-background-decoration="grid"] body { background-image: linear-gradient(color-mix(in srgb, var(--documentation-border) 26%, transparent) 1px, transparent 1px), linear-gradient(90deg, color-mix(in srgb, var(--documentation-border) 26%, transparent) 1px, transparent 1px); background-attachment: fixed; background-size: 32px 32px; }
3113
3141
  body:has(.documentation-modal-layer), body:has(.documentation-mobile-nav) { overflow: hidden; }
3114
3142
  button, input, textarea { font: inherit; }
3115
- button, a { -webkit-tap-highlight-color: transparent; }
3143
+ button, a, summary, label { -webkit-tap-highlight-color: transparent; }
3116
3144
  a { color: inherit; }
3117
3145
  button:focus-visible, a:focus-visible, input:focus-visible, textarea:focus-visible, summary:focus-visible { outline: 2px solid var(--documentation-focus-ring); outline-offset: 3px; }
3118
3146
  ::selection { background: color-mix(in srgb, var(--documentation-accent) 24%, transparent); }
3147
+ /* Chrome is an instrument, not a document: its labels never select and its
3148
+ * links never spawn the native drag ghost. The article prose, assistant
3149
+ * answers, and every input stay fully selectable. (The router's dragstart
3150
+ * chokepoint enforces the no-ghost rule in engines without -webkit-user-drag.) */
3151
+ .documentation-header, .documentation-sidebar, .documentation-mobile-nav, .documentation-outline, .documentation-outline-disclosure > summary, .documentation-breadcrumbs, .documentation-article-meta, .documentation-pagination, .documentation-search-dialog, .documentation-launcher-dock, .documentation-assistant > header, .documentation-assistant-suggestions, .documentation-assistant > footer, .documentation-tab-buttons, .documentation-code-actions, .documentation-theme-controls { user-select: none; -webkit-user-select: none; }
3152
+ .documentation-search-dialog input, .documentation-launcher-dock input, .documentation-search-results { user-select: text; -webkit-user-select: text; }
3153
+ :is(.documentation-header, .documentation-sidebar, .documentation-mobile-nav, .documentation-outline, .documentation-breadcrumbs, .documentation-article-meta, .documentation-pagination, .documentation-search-dialog) :is(a, img) { -webkit-user-drag: none; }
3119
3154
 
3120
3155
  .documentation-skip-link { position: fixed; z-index: 200; top: -64px; left: 16px; padding: 9px 13px; border-radius: 8px; background: var(--documentation-text); color: var(--documentation-bg); font-weight: 650; text-decoration: none; }
3121
3156
  .documentation-skip-link:focus { top: 12px; }
3122
- .documentation-app.is-navigating::before { content: ""; position: fixed; z-index: 240; inset: 0 auto auto 0; width: 42%; height: 2px; background: linear-gradient(90deg, var(--documentation-accent), var(--documentation-accent-2)); box-shadow: 0 0 14px color-mix(in srgb, var(--documentation-accent-2) 48%, transparent); animation: documentation-navigation-progress .8s ease-in-out infinite alternate; }
3123
- ::view-transition-old(documentation-article) { animation: documentation-page-out .11s ease-in both; }
3124
- ::view-transition-new(documentation-article) { animation: documentation-page-in .16s ease-out both; }
3125
- /* Only the article animates. Without these, the browser's default root
3126
- * cross-fade snapshots the whole viewport and visibly fades over the fixed
3127
- * assistant launcher/panel on every client navigation. */
3128
- ::view-transition-group(root) { animation: none; }
3129
- ::view-transition-old(root), ::view-transition-new(root) { animation: none; }
3130
- ::view-transition-old(documentation-assistant), ::view-transition-new(documentation-assistant),
3131
- ::view-transition-old(documentation-assistant-launcher), ::view-transition-new(documentation-assistant-launcher) { animation: none; }
3157
+ /* The only navigation feedback. The article itself never animates: a route
3158
+ * swap is a hard cut committed in one frame, because any overlap of two text
3159
+ * layers — any fade, slide, or view transition — reads as ghosting. */
3160
+ .documentation-app.is-navigating::before { content: ""; position: fixed; z-index: 240; inset: 0 auto auto 0; width: 42%; height: 2px; background: var(--documentation-accent); animation: documentation-navigation-progress .8s ease-in-out infinite alternate; }
3132
3161
 
3133
3162
  `;
3134
3163
 
@@ -3137,7 +3166,7 @@ var DOCUMENTATION_CONTENT_CSS = String.raw`
3137
3166
  .documentation-main { min-width: 0; margin-left: var(--documentation-sidebar-width); margin-right: 0; transition: margin-right .24s ease; }
3138
3167
  .documentation-reader-grid { display: grid; grid-template-columns: minmax(0, 720px) 250px; justify-content: center; gap: 70px; width: 100%; padding: 62px 52px 96px; }
3139
3168
  .documentation-reader-column { display: flex; min-width: 0; min-height: calc(100vh - var(--documentation-header-height) - 158px); flex-direction: column; }
3140
- .documentation-article { display: flex; min-width: 0; flex: 1; flex-direction: column; view-transition-name: documentation-article; }
3169
+ .documentation-article { display: flex; min-width: 0; flex: 1; flex-direction: column; }
3141
3170
  .documentation-breadcrumbs { display: none; align-items: center; gap: 5px; margin-bottom: 24px; color: var(--documentation-muted); font-size: 13px; }
3142
3171
  .documentation-breadcrumbs span { display: inline-flex; align-items: center; gap: 5px; }
3143
3172
  .documentation-breadcrumbs svg { width: 12px; height: 12px; }
@@ -3168,7 +3197,10 @@ var DOCUMENTATION_CONTENT_CSS = String.raw`
3168
3197
 
3169
3198
  .documentation-prose { color: var(--documentation-text-soft); }
3170
3199
  .documentation-prose > :first-child { margin-top: 0; }
3171
- .documentation-prose h1, .documentation-prose h2, .documentation-prose h3, .documentation-prose h4, .documentation-prose h5, .documentation-prose h6 { position: relative; color: var(--documentation-text); font-family: var(--documentation-font-heading); scroll-margin-top: 96px; }
3200
+ /* Anchor clearance is owned once, by scroll-padding-top on the html element
3201
+ * — a per-heading scroll-margin here stacked with it and landed anchors a
3202
+ * full header-height too low. */
3203
+ .documentation-prose h1, .documentation-prose h2, .documentation-prose h3, .documentation-prose h4, .documentation-prose h5, .documentation-prose h6 { position: relative; color: var(--documentation-text); font-family: var(--documentation-font-heading); }
3172
3204
  .documentation-prose h1 { margin: 48px 0 18px; font-size: 30px; letter-spacing: -.025em; line-height: 1.2; }
3173
3205
  .documentation-prose h2 { margin: 50px 0 16px; padding-top: 5px; font-size: 25px; font-weight: 625; letter-spacing: -.025em; line-height: 1.28; }
3174
3206
  .documentation-prose h3 { margin: 34px 0 12px; font-size: 20px; font-weight: 620; letter-spacing: -.015em; line-height: 1.4; }
@@ -3200,8 +3232,12 @@ var DOCUMENTATION_CONTENT_CSS = String.raw`
3200
3232
  .documentation-code-actions button { display: grid; place-items: center; width: 30px; height: 30px; padding: 0; border: 1px solid rgba(255, 255, 255, .14); border-radius: 7px; background: color-mix(in srgb, var(--documentation-code-panel) 88%, transparent); color: #aeb5c6; cursor: pointer; backdrop-filter: blur(6px); }
3201
3233
  .documentation-code-actions button:hover { background: rgba(255, 255, 255, .14); color: #fff; }
3202
3234
  .documentation-code-actions svg { width: 15px; height: 15px; }
3203
- .documentation-code-language { position: absolute; z-index: 1; top: 14px; left: 20px; color: #7f889c; font: 650 11.5px/1 var(--documentation-font-mono); letter-spacing: .06em; text-transform: uppercase; pointer-events: none; }
3204
- .documentation-code-block:has(.documentation-code-language) pre { padding-top: 38px; }
3235
+ /* The language rides in the hover actions row as a passive chip instead of a
3236
+ * permanently visible label that cost every block 38px of top padding. */
3237
+ .documentation-code-language { display: inline-flex; align-items: center; height: 30px; padding: 0 9px; border: 1px solid rgba(255, 255, 255, .14); border-radius: 7px; background: color-mix(in srgb, var(--documentation-code-panel) 88%, transparent); color: #7f889c; font: 650 11px/1 var(--documentation-font-mono); letter-spacing: .06em; text-transform: uppercase; pointer-events: none; backdrop-filter: blur(6px); }
3238
+ /* Fence titles (filenames) get a slim header bar above the code. */
3239
+ .documentation-code-title { display: flex; align-items: center; min-height: 36px; padding: 0 16px; border: 1px solid color-mix(in srgb, var(--documentation-border-strong) 50%, #000); border-bottom: 0; border-radius: 12px 12px 0 0; background: var(--documentation-code-panel); color: #aeb5c6; font: 600 12px/1.3 var(--documentation-font-mono); }
3240
+ .documentation-code-block:has(.documentation-code-title) pre { margin-top: 0; border-top-left-radius: 0; border-top-right-radius: 0; }
3205
3241
 
3206
3242
  .hljs-keyword, .hljs-selector-tag, .hljs-literal, .hljs-section, .hljs-link { color: #b7a7ff; }
3207
3243
  .hljs-string, .hljs-title, .hljs-name, .hljs-type, .hljs-attribute, .hljs-symbol, .hljs-bullet, .hljs-addition { color: #73dfb4; }
@@ -3222,7 +3258,8 @@ var DOCUMENTATION_CONTENT_CSS = String.raw`
3222
3258
  :root[data-code-mode="system"][data-theme="light"] .documentation-prose pre { border-color: var(--documentation-border); background: linear-gradient(145deg, #f7f8fb, #f1f3f7); color: var(--documentation-code-plain); box-shadow: 0 8px 26px rgba(15, 18, 28, .06); }
3223
3259
  :root[data-code-mode="system"][data-theme="light"] .documentation-code-actions button { border-color: rgba(17, 19, 26, .12); background: rgba(255, 255, 255, .82); color: #606675; }
3224
3260
  :root[data-code-mode="system"][data-theme="light"] .documentation-code-actions button:hover { background: #fff; color: #11131a; }
3225
- :root[data-code-mode="system"][data-theme="light"] .documentation-code-language { color: #757c8c; }
3261
+ :root[data-code-mode="system"][data-theme="light"] .documentation-code-language { border-color: rgba(17, 19, 26, .12); background: rgba(255, 255, 255, .82); color: #757c8c; }
3262
+ :root[data-code-mode="system"][data-theme="light"] .documentation-code-title { border-color: var(--documentation-border); background: #eef1f6; color: #5c6270; }
3226
3263
  :root[data-code-mode="system"][data-theme="light"] :is(.hljs-keyword, .hljs-selector-tag, .hljs-literal, .hljs-section, .hljs-link) { color: var(--documentation-code-keyword); }
3227
3264
  :root[data-code-mode="system"][data-theme="light"] :is(.hljs-string, .hljs-title, .hljs-name, .hljs-type, .hljs-attribute, .hljs-symbol, .hljs-bullet, .hljs-addition) { color: var(--documentation-code-string); }
3228
3265
  :root[data-code-mode="system"][data-theme="light"] :is(.hljs-number, .hljs-meta, .hljs-built_in, .hljs-builtin-name, .hljs-params) { color: var(--documentation-code-number); }
@@ -3236,15 +3273,17 @@ var DOCUMENTATION_CONTENT_CSS = String.raw`
3236
3273
  .documentation-prose tr:last-child td { border-bottom: 0; }
3237
3274
  .documentation-prose th { color: var(--documentation-text); font-size: 13px; font-weight: 700; letter-spacing: .02em; }
3238
3275
 
3239
- .documentation-callout { --callout-accent: var(--documentation-accent); position: relative; margin: 24px 0; padding: 16px 18px 16px 20px; overflow: hidden; border: 1px solid color-mix(in srgb, var(--callout-accent) 25%, var(--documentation-border)); border-radius: 11px; background: linear-gradient(105deg, color-mix(in srgb, var(--callout-accent) 7%, var(--documentation-surface)), var(--documentation-surface)); }
3276
+ .documentation-callout { --callout-accent: var(--documentation-accent); position: relative; margin: 24px 0; padding: 16px 18px 16px 20px; overflow: hidden; border: 1px solid color-mix(in srgb, var(--callout-accent) 25%, var(--documentation-border)); border-radius: 11px; background: color-mix(in srgb, var(--callout-accent) 6%, var(--documentation-surface)); }
3240
3277
  .documentation-callout::before { content: ""; position: absolute; inset: 0 auto 0 0; width: 2px; background: var(--callout-accent); }
3241
3278
  .documentation-callout > strong { display: block; margin-bottom: 3px; color: color-mix(in srgb, var(--callout-accent) 72%, var(--documentation-text)); font-size: 14px; }
3242
3279
  .documentation-callout > :last-child { margin-bottom: 0; }
3243
- .documentation-callout-warning { --callout-accent: #e58a21; }
3280
+ .documentation-callout-warning { --callout-accent: #c9771a; }
3244
3281
  .documentation-callout-tip { --callout-accent: #17a673; }
3245
3282
  .documentation-callout-info { --callout-accent: #278fdb; }
3246
3283
  .documentation-callout-note { --callout-accent: var(--documentation-accent); }
3247
- .documentation-card { display: grid; grid-template-columns: 1fr auto; align-items: center; gap: 12px; margin: 14px 0; padding: 16px 17px; border: 1px solid var(--documentation-border); border-radius: 11px; background: var(--documentation-surface); box-shadow: var(--documentation-shadow-sm); text-decoration: none !important; transition: border-color .16s, box-shadow .16s, transform .16s; }
3284
+ /* Card bodies are body copy, not links — without this the anchor's link color
3285
+ * bleeds into every description. */
3286
+ .documentation-card { color: var(--documentation-text-soft); display: grid; grid-template-columns: 1fr auto; align-items: center; gap: 12px; margin: 14px 0; padding: 16px 17px; border: 1px solid var(--documentation-border); border-radius: 11px; background: var(--documentation-surface); box-shadow: var(--documentation-shadow-sm); text-decoration: none !important; transition: border-color .16s, box-shadow .16s, transform .16s; }
3248
3287
  .documentation-card:hover { border-color: color-mix(in srgb, var(--documentation-accent) 42%, var(--documentation-border)); box-shadow: 0 7px 24px rgba(15, 18, 28, .07); transform: translateY(-1px); }
3249
3288
  .documentation-card strong { display: block; margin-bottom: 2px; }
3250
3289
  .documentation-accordion-group { margin: 21px 0; border: 1px solid var(--documentation-border); border-radius: 11px; overflow: hidden; }
@@ -3286,7 +3325,7 @@ var DOCUMENTATION_CONTENT_CSS = String.raw`
3286
3325
  .documentation-playground > p { color: var(--documentation-muted); font-size: 12px; }
3287
3326
  .documentation-playground label { display: grid; gap: 5px; margin: 13px 0; color: var(--documentation-muted); font-size: 11px; font-weight: 650; }
3288
3327
  .documentation-playground input, .documentation-playground textarea { width: 100%; padding: 10px; border: 1px solid var(--documentation-border-strong); border-radius: 8px; background: var(--documentation-surface); color: var(--documentation-text); font: 12.5px/1.55 var(--documentation-font-mono); resize: vertical; }
3289
- .documentation-playground > button { padding: 9px 13px; border: 0; border-radius: 8px; background: var(--documentation-accent); color: white; cursor: pointer; font-size: 12px; font-weight: 680; }
3328
+ .documentation-playground > button { padding: 9px 13px; border: 0; border-radius: 8px; background: var(--documentation-accent); color: var(--documentation-accent-contrast); cursor: pointer; font-size: 12px; font-weight: 680; }
3290
3329
  .documentation-playground > button:disabled { opacity: .58; cursor: wait; }
3291
3330
  .documentation-playground > pre { max-height: 320px; overflow: auto; margin: 14px 0 0; padding: 13px; border-radius: 8px; background: var(--documentation-code-bg); color: var(--documentation-code-text); font: 11.5px/1.55 var(--documentation-font-mono); white-space: pre-wrap; }
3292
3331
 
@@ -3320,7 +3359,6 @@ var DOCUMENTATION_NAVIGATION_CSS = String.raw`
3320
3359
  .documentation-header { position: fixed; z-index: 50; inset: 0 0 auto; display: grid; grid-template-columns: var(--documentation-sidebar-width) minmax(300px, 1fr) auto; align-items: center; height: var(--documentation-header-height); border-bottom: 1px solid color-mix(in srgb, var(--documentation-border) 84%, transparent); background: color-mix(in srgb, var(--documentation-bg) 91%, transparent); backdrop-filter: blur(18px) saturate(1.15); transition: right .24s ease; }
3321
3360
  .documentation-brand { display: flex; align-items: center; gap: 10px; min-width: 0; height: 100%; padding: 0 23px; color: var(--documentation-text); text-decoration: none; }
3322
3361
  .documentation-brand-mark { position: relative; display: grid; place-items: center; width: 27px; height: 27px; color: var(--documentation-accent); }
3323
- .documentation-brand-mark::before { content: ""; position: absolute; inset: -7px; border-radius: 50%; background: radial-gradient(circle, color-mix(in srgb, var(--documentation-accent-2) 15%, transparent), transparent 68%); }
3324
3362
  .documentation-brand-mark svg { position: relative; width: 27px; height: 27px; }
3325
3363
  .documentation-brand-name { overflow: hidden; font-size: 16px; font-weight: 720; letter-spacing: -.025em; text-overflow: ellipsis; white-space: nowrap; }
3326
3364
  .documentation-brand-product { padding-left: 10px; border-left: 1px solid var(--documentation-border-strong); color: var(--documentation-muted); font-size: 13px; font-weight: 600; letter-spacing: .04em; }
@@ -3353,8 +3391,10 @@ var DOCUMENTATION_NAVIGATION_CSS = String.raw`
3353
3391
  .documentation-nav-link > span { min-width: 0; overflow-wrap: anywhere; }
3354
3392
  .documentation-nav-link > svg { flex: 0 0 auto; width: 12px; height: 12px; }
3355
3393
  .documentation-nav-link:hover { background: var(--documentation-panel); color: var(--documentation-text); }
3356
- .documentation-nav-link.is-active { position: relative; background: linear-gradient(90deg, color-mix(in srgb, var(--documentation-accent) 11%, transparent), color-mix(in srgb, var(--documentation-accent-2) 5%, transparent)); color: color-mix(in srgb, var(--documentation-accent) 77%, var(--documentation-text)); font-weight: 650; }
3357
- .documentation-nav-link.is-active::before { content: ""; position: absolute; inset: 8px auto 8px -5px; width: 2px; border-radius: 4px; background: linear-gradient(var(--documentation-accent), var(--documentation-accent-2)); box-shadow: 0 0 10px color-mix(in srgb, var(--documentation-accent-2) 52%, transparent); }
3394
+ /* Paper, not neon: the active state is a flat tint and a solid hairline —
3395
+ * no gradients, no glow. */
3396
+ .documentation-nav-link.is-active { position: relative; background: color-mix(in srgb, var(--documentation-accent) 10%, transparent); color: color-mix(in srgb, var(--documentation-accent) 72%, var(--documentation-text)); font-weight: 650; }
3397
+ .documentation-nav-link.is-active::before { content: ""; position: absolute; inset: 8px auto 8px -5px; width: 2px; border-radius: 4px; background: var(--documentation-accent); }
3358
3398
  .documentation-nav-folder { margin: 2px 0; }
3359
3399
  .documentation-nav-folder > summary { display: flex; align-items: center; justify-content: space-between; min-height: 34px; padding: 6px 9px; border-radius: 8px; color: var(--documentation-muted); cursor: pointer; font-size: 14px; font-weight: 620; list-style: none; }
3360
3400
  .documentation-nav-folder > summary::-webkit-details-marker { display: none; }
@@ -3415,30 +3455,34 @@ var DOCUMENTATION_OVERLAYS_CSS = String.raw`
3415
3455
  .documentation-mobile-nav > footer { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 13px; padding: 13px 18px; border-top: 1px solid var(--documentation-border); }
3416
3456
  .documentation-mobile-nav > footer a { color: var(--documentation-muted); font-size: 13px; text-decoration: none; }
3417
3457
 
3418
- /* Sticky inside the reading column instead of fixed to the viewport: it tracks
3419
- * the column's centre line, never covers the sidebar or outline, and scrolls
3420
- * away above the pagination rather than sitting on top of it. */
3421
- .documentation-launcher-dock { position: sticky; z-index: 40; bottom: 0; display: flex; justify-content: center; margin-top: auto; padding: 44px 0 16px; pointer-events: none; }
3422
- .documentation-launcher-dock::before { content: ""; position: absolute; z-index: -1; inset: 0; background: linear-gradient(to bottom, transparent, var(--documentation-brand-bg) 58%); }
3458
+ /* The launcher owns a reserved slot in the reading column: sticky at the
3459
+ * viewport bottom while reading, ordinary flow above the pagination once the
3460
+ * end of the article arrives. It is present on the whole page — no auto-hide,
3461
+ * no protective gradient, no mask. The pill's own glass is its legibility
3462
+ * over prose, dark code, and images, and its in-flow slot means it never
3463
+ * crosses the pagination. */
3464
+ .documentation-launcher-dock { position: sticky; z-index: 40; bottom: 0; display: flex; justify-content: center; margin-top: auto; padding: 30px 0 18px; pointer-events: none; }
3423
3465
  .documentation-launcher-dock + .documentation-pagination { margin-top: 0; }
3424
- .documentation-assistant-launcher { view-transition-name: documentation-assistant-launcher; position: relative; display: grid; grid-template-columns: fit-content(40%) minmax(0, 1fr) auto auto; align-items: center; gap: 0; width: min(452px, 100%); min-height: 48px; padding: 5px; border: 1px solid color-mix(in srgb, var(--documentation-border-strong) 92%, var(--documentation-accent)); border-radius: 13px; background: color-mix(in srgb, var(--documentation-surface-raised) 96%, transparent); color: var(--documentation-text); box-shadow: 0 18px 45px rgba(15, 18, 28, .11), 0 2px 8px rgba(15, 18, 28, .05); pointer-events: auto; backdrop-filter: blur(18px) saturate(1.1); transition: border-color .16s, box-shadow .16s, transform .16s; }
3425
- .documentation-assistant-launcher:hover { border-color: color-mix(in srgb, var(--documentation-accent) 32%, var(--documentation-border-strong)); box-shadow: 0 20px 48px rgba(15, 18, 28, .14), 0 2px 8px rgba(15, 18, 28, .06); transform: translateY(-1px); }
3426
- .documentation-assistant-launcher input { min-width: 0; height: 36px; padding: 0 12px; border: 0; outline: 0; background: transparent; color: var(--documentation-text); font-size: 14px; }
3466
+ .documentation-assistant-launcher { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) auto auto; align-items: center; gap: 0; width: min(452px, 100%); min-height: 48px; padding: 5px; border: 1px solid var(--documentation-glass-border); border-radius: 15px; background: var(--documentation-glass-bg); color: var(--documentation-text); box-shadow: inset 0 1px 0 var(--documentation-glass-highlight), 0 16px 40px rgba(15, 18, 28, .12), 0 2px 8px rgba(15, 18, 28, .05); pointer-events: auto; backdrop-filter: blur(20px) saturate(1.2); -webkit-backdrop-filter: blur(20px) saturate(1.2); transition: border-color .16s, box-shadow .16s, transform .22s cubic-bezier(.4, 0, .2, 1); }
3467
+ .documentation-assistant-launcher:hover { border-color: color-mix(in srgb, var(--documentation-accent) 32%, var(--documentation-border-strong)); box-shadow: inset 0 1px 0 var(--documentation-glass-highlight), 0 20px 48px rgba(15, 18, 28, .15), 0 2px 8px rgba(15, 18, 28, .06); transform: translateY(-1px); }
3468
+ .documentation-assistant-launcher:focus-within { border-color: color-mix(in srgb, var(--documentation-accent) 48%, var(--documentation-border-strong)); box-shadow: inset 0 1px 0 var(--documentation-glass-highlight), 0 0 0 3px color-mix(in srgb, var(--documentation-accent) 10%, transparent), 0 16px 40px rgba(15, 18, 28, .12); }
3469
+ .documentation-assistant-launcher input { min-width: 0; height: 36px; padding: 0 6px 0 14px; border: 0; outline: 0; background: transparent; color: var(--documentation-text); font-size: 14px; }
3427
3470
  .documentation-assistant-launcher input::placeholder { color: var(--documentation-muted); }
3428
- .documentation-launcher-send { display: grid; place-items: center; height: 36px; border: 0; border-radius: 9px; cursor: pointer; }
3429
3471
  /* The 40% cap lives on the grid track: a percentage max-width here would
3430
3472
  * resolve against that track instead of the launcher. */
3431
- .documentation-launcher-agent { display: flex; align-items: center; gap: 4px; min-width: 0; height: 36px; padding: 0 13px 0 9px; border: 0; border-right: 1px solid var(--documentation-border); border-radius: 0; background: transparent; color: var(--documentation-text-soft); cursor: pointer; font-size: 12.5px; font-weight: 650; white-space: nowrap; }
3432
- .documentation-launcher-agent-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
3433
- .documentation-launcher-agent:hover { color: var(--documentation-accent); }
3434
3473
  .documentation-launcher-hint { display: grid; grid-auto-flow: column; gap: 3px; padding-right: 8px; }
3435
3474
  .documentation-launcher-hint kbd { padding: 2px 5px; border: 1px solid var(--documentation-border); border-radius: 5px; background: var(--documentation-panel); color: var(--documentation-faint); font: 600 11px/1.3 var(--documentation-font-mono); }
3436
- .documentation-launcher-send { width: 36px; padding: 0; background: var(--documentation-accent); color: #fff; }
3437
- .documentation-launcher-send:disabled { background: var(--documentation-panel); color: var(--documentation-faint); cursor: default; }
3438
- .documentation-launcher-send svg { width: 15px; }
3475
+ /* One send-button spec for the launcher and the composer: a circular accent
3476
+ * button with a gentle press cycle, dim while empty. */
3477
+ .documentation-launcher-send, .documentation-assistant-composer > button { display: grid; flex: 0 0 auto; place-items: center; width: 32px; height: 32px; padding: 0; border: 0; border-radius: 999px; background: var(--documentation-accent); color: var(--documentation-accent-contrast); cursor: pointer; transition: background-color .15s ease, color .15s ease, transform .15s ease; }
3478
+ .documentation-launcher-send { width: 36px; height: 36px; }
3479
+ .documentation-launcher-send:hover:not(:disabled), .documentation-assistant-composer > button:hover:not(:disabled) { transform: scale(1.06); }
3480
+ .documentation-launcher-send:active:not(:disabled), .documentation-assistant-composer > button:active:not(:disabled) { transform: scale(.96); }
3481
+ .documentation-launcher-send:disabled, .documentation-assistant-composer > button:disabled { background: var(--documentation-panel-strong); color: var(--documentation-faint); cursor: default; }
3482
+ .documentation-launcher-send svg, .documentation-assistant-composer > button svg { width: 14px; height: 14px; }
3439
3483
  /* Docked beside the article on desktop so the page being asked about stays
3440
3484
  * readable; the narrow breakpoints below restore the floating card and sheet. */
3441
- .documentation-assistant { view-transition-name: documentation-assistant; position: fixed; z-index: 90; inset: var(--documentation-header-height) 0 0 auto; display: grid; grid-template-rows: auto minmax(0, 1fr) auto auto; width: var(--documentation-assistant-width); overflow: hidden; border-left: 1px solid var(--documentation-border-strong); background: var(--documentation-surface); box-shadow: -18px 0 48px rgba(15, 18, 28, .06); animation: documentation-assistant-dock-in .2s ease-out; }
3485
+ .documentation-assistant { position: fixed; z-index: 90; inset: var(--documentation-header-height) 0 0 auto; display: grid; grid-template-rows: auto minmax(0, 1fr) auto auto; width: var(--documentation-assistant-width); overflow: hidden; border-left: 1px solid var(--documentation-border-strong); background: var(--documentation-surface); box-shadow: -18px 0 48px rgba(15, 18, 28, .06); animation: documentation-assistant-dock-in .2s ease-out; }
3442
3486
  .documentation-app.is-assistant-open .documentation-main { margin-right: var(--documentation-assistant-width); }
3443
3487
  .documentation-app.is-assistant-open .documentation-header { right: var(--documentation-assistant-width); }
3444
3488
  .documentation-assistant > header { display: flex; align-items: center; justify-content: space-between; min-height: 54px; padding: 0 11px 0 18px; border-bottom: 1px solid var(--documentation-border); }
@@ -3455,7 +3499,7 @@ var DOCUMENTATION_OVERLAYS_CSS = String.raw`
3455
3499
  .documentation-assistant-message > div { min-width: 0; max-width: 590px; }
3456
3500
  .documentation-assistant-message.is-user { justify-content: flex-end; margin-left: 54px; }
3457
3501
  .documentation-assistant-message.is-user > div { padding: 8px 11px; border: 1px solid var(--documentation-border); border-radius: 10px; background: var(--documentation-panel); color: var(--documentation-text); }
3458
- .documentation-assistant-message.is-error > div { color: #c64b50; }
3502
+ .documentation-assistant-message.is-error > div { padding: 10px 13px; border: 1px solid color-mix(in srgb, #d05a60 32%, var(--documentation-border)); border-radius: 10px; background: color-mix(in srgb, #d05a60 7%, var(--documentation-surface)); color: color-mix(in srgb, #d05a60 58%, var(--documentation-text)); font-size: 13.5px; }
3459
3503
  .documentation-assistant-message a { color: color-mix(in srgb, var(--documentation-accent) 79%, var(--documentation-text)); font-weight: 580; text-underline-offset: 3px; }
3460
3504
  .documentation-assistant-markdown > :first-child { margin-top: 0; }
3461
3505
  .documentation-assistant-markdown > :last-child { margin-bottom: 0; }
@@ -3474,19 +3518,17 @@ var DOCUMENTATION_OVERLAYS_CSS = String.raw`
3474
3518
  .documentation-assistant-suggestions p { margin: 0 0 1px; color: var(--documentation-faint); font-size: 12px; font-weight: 650; letter-spacing: .035em; text-transform: uppercase; }
3475
3519
  .documentation-assistant-suggestions button { min-height: 40px; padding: 9px 12px; border: 1px solid var(--documentation-border); border-radius: 9px; background: var(--documentation-bg); color: var(--documentation-muted); cursor: pointer; font-size: 13.5px; text-align: left; transition: border-color .14s, background .14s, color .14s; }
3476
3520
  .documentation-assistant-suggestions button:hover { border-color: var(--documentation-border-strong); background: var(--documentation-panel); color: var(--documentation-text); }
3477
- .documentation-assistant-composer { display: flex; align-items: flex-end; gap: 7px; margin: 0 16px 9px; padding: 7px; border: 1px solid var(--documentation-border-strong); border-radius: 11px; background: var(--documentation-bg); box-shadow: 0 3px 12px rgba(15, 18, 28, .045); }
3521
+ .documentation-assistant-composer { display: flex; align-items: flex-end; gap: 8px; margin: 0 16px 10px; padding: 8px; border: 1px solid var(--documentation-border-strong); border-radius: 16px; background: var(--documentation-surface-raised); box-shadow: 0 3px 12px rgba(15, 18, 28, .045); transition: border-color .15s ease, box-shadow .15s ease; }
3478
3522
  .documentation-assistant-composer:focus-within { border-color: color-mix(in srgb, var(--documentation-accent) 52%, var(--documentation-border)); box-shadow: 0 0 0 3px color-mix(in srgb, var(--documentation-accent) 9%, transparent); }
3479
- .documentation-assistant-composer textarea { min-height: 41px; max-height: 160px; flex: 1; padding: 4px 5px; resize: none; border: 0; outline: 0; background: transparent; color: var(--documentation-text); font-size: 14px; line-height: 1.5; }
3480
- .documentation-assistant-composer button { display: grid; place-items: center; width: 32px; height: 32px; padding: 0; border: 0; border-radius: 8px; background: var(--documentation-accent); color: white; cursor: pointer; }
3481
- .documentation-assistant-composer button:disabled { background: var(--documentation-panel-strong); color: var(--documentation-faint); cursor: default; }
3523
+ /* The field grows with its content (the runtime sets the height); it never
3524
+ * shows a scrollbar until the growth cap, and never clips a glyph. */
3525
+ .documentation-assistant-composer textarea { min-height: 24px; max-height: 160px; flex: 1; padding: 5px 6px; resize: none; border: 0; outline: 0; background: transparent; color: var(--documentation-text); font-size: 14px; line-height: 1.5; overflow-y: hidden; scrollbar-width: thin; }
3482
3526
  .documentation-assistant > footer { padding: 0 18px 12px; color: var(--documentation-faint); font-size: 12px; text-align: center; }
3483
3527
  @keyframes documentation-fade-in { from { opacity: 0; } }
3484
3528
  @keyframes documentation-dialog-in { from { opacity: 0; transform: translateY(-8px) scale(.99); } }
3485
3529
  @keyframes documentation-drawer-in { from { transform: translateX(-24px); } }
3486
3530
  @keyframes documentation-assistant-dock-in { from { transform: translateX(24px); opacity: .5; } }
3487
3531
  @keyframes documentation-assistant-in { from { transform: translateX(-50%) translateY(18px) scale(.985); opacity: .7; } }
3488
- @keyframes documentation-page-out { to { opacity: 0; transform: translateY(-3px); } }
3489
- @keyframes documentation-page-in { from { opacity: 0; transform: translateY(4px); } }
3490
3532
  @keyframes documentation-activity { 50% { opacity: .42; transform: scale(.82); } }
3491
3533
  @keyframes documentation-navigation-progress { from { transform: translateX(-20%); } to { transform: translateX(155%); } }
3492
3534
 
@@ -3514,8 +3556,9 @@ var DOCUMENTATION_RESPONSIVE_CSS = String.raw`
3514
3556
  .documentation-top-links { display: none; }
3515
3557
  .documentation-breadcrumbs { display: flex; }
3516
3558
  .documentation-outline-disclosure { display: block; }
3517
- /* Too narrow to dock beside the article; fall back to the floating card. */
3518
- .documentation-assistant { inset: auto auto 18px 50%; width: min(620px, calc(100vw - 36px)); height: min(570px, calc(100vh - 94px)); border: 1px solid var(--documentation-border-strong); border-radius: 16px; box-shadow: 0 28px 80px rgba(15, 18, 28, .18), 0 6px 22px rgba(15, 18, 28, .08); transform: translateX(-50%); animation: documentation-assistant-in .2s ease-out; }
3559
+ /* Too narrow to dock beside the article; fall back to the floating card.
3560
+ * The article passes beneath it, so this surface is honest glass. */
3561
+ .documentation-assistant { inset: auto auto 18px 50%; width: min(620px, calc(100vw - 36px)); height: min(570px, calc(100vh - 94px)); border: 1px solid var(--documentation-glass-border); border-radius: 16px; background: var(--documentation-glass-bg); backdrop-filter: blur(24px) saturate(1.2); -webkit-backdrop-filter: blur(24px) saturate(1.2); box-shadow: inset 0 1px 0 var(--documentation-glass-highlight), var(--documentation-shadow-lg); transform: translateX(-50%); animation: documentation-assistant-in .2s ease-out; }
3519
3562
  .documentation-app.is-assistant-open .documentation-main { margin-right: 0; }
3520
3563
  .documentation-app.is-assistant-open .documentation-header { right: 0; }
3521
3564
  }
@@ -3555,8 +3598,6 @@ var DOCUMENTATION_RESPONSIVE_CSS = String.raw`
3555
3598
  .documentation-search-results { max-height: none; }
3556
3599
  .documentation-search-dialog > footer { justify-content: center; }
3557
3600
  .documentation-launcher-dock { padding-bottom: 12px; }
3558
- .documentation-launcher-agent { padding: 0 9px; }
3559
- .documentation-launcher-agent .documentation-launcher-agent-name { display: none; }
3560
3601
  .documentation-launcher-hint { display: none; }
3561
3602
  .documentation-assistant { inset: auto auto 0 0; width: 100%; height: calc(100vh - 8px); transform: none; border-width: 1px 0 0; border-radius: 18px 18px 0 0; }
3562
3603
  .documentation-assistant-suggestions { grid-template-columns: 1fr; }
@@ -3585,6 +3626,7 @@ function renderPage(options, assets = {}, runtime = createPageRuntime(options))
3585
3626
  const { data: runtimeData, document: runtimeDocument } = runtime;
3586
3627
  const theme = runtimeData.config.theme;
3587
3628
  const accent = documentationAccent(theme);
3629
+ const accentDark = validCssColor(theme.accentDark) ? theme.accentDark : void 0;
3588
3630
  const background = validCssColor(theme.background) ? theme.background : "#fbfcfe";
3589
3631
  const backgroundDark = validCssColor(theme.backgroundDark) ? theme.backgroundDark : "#0c0e14";
3590
3632
  const defaultMode = theme.defaultMode ?? "system";
@@ -3613,6 +3655,7 @@ function renderPage(options, assets = {}, runtime = createPageRuntime(options))
3613
3655
  <meta property="og:description" content="${escapeHtml(runtimeDocument.openGraph["og:description"] ?? "")}">
3614
3656
  ${runtimeDocument.openGraph["og:url"] ? `<meta property="og:url" content="${escapeHtml(runtimeDocument.openGraph["og:url"])}">` : ""}
3615
3657
  ${config.seo.ogImage ? `<meta property="og:image" content="${escapeHtml(config.seo.ogImage)}">` : ""}
3658
+ ${config.seo.ogImage ? `<meta name="twitter:image" content="${escapeHtml(config.seo.ogImage)}">` : ""}
3616
3659
  <meta name="twitter:card" content="${config.seo.ogImage ? "summary_large_image" : "summary"}">
3617
3660
  <meta name="theme-color" media="(prefers-color-scheme: light)" content="${background}">
3618
3661
  <meta name="theme-color" media="(prefers-color-scheme: dark)" content="${backgroundDark}">
@@ -3621,7 +3664,7 @@ function renderPage(options, assets = {}, runtime = createPageRuntime(options))
3621
3664
  ${fontPreloads}
3622
3665
  <link rel="stylesheet" href="${assetRoot}/documentation.css">
3623
3666
  ${(assets.customStylesheets ?? []).map((href) => `<link rel="stylesheet" href="${escapeHtml(href)}">`).join("\n ")}
3624
- <style>${fontFaces}:root{--documentation-accent:${accent};--documentation-brand-bg:${background};--documentation-brand-bg-dark:${backgroundDark};--documentation-font-body:${bodyFont};--documentation-font-heading:${headingFont};--documentation-font-mono:${monoFont}}</style>
3667
+ <style>${fontFaces}:root{--documentation-accent-light:${accent};${accentDark ? `--documentation-accent-dark:${accentDark};` : ""}--documentation-brand-bg:${background};--documentation-brand-bg-dark:${backgroundDark};--documentation-font-body:${bodyFont};--documentation-font-heading:${headingFont};--documentation-font-mono:${monoFont}}</style>
3625
3668
  <script src="${assetRoot}/documentation-theme.js"></script>
3626
3669
  </head>
3627
3670
  <body data-route="${escapeHtml(page.route)}">