@vanillaskyai/video 0.7.1 → 0.8.1

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 (89) hide show
  1. package/CHANGELOG.md +63 -0
  2. package/PUBLIC-API.md +83 -79
  3. package/README.md +20 -15
  4. package/dist/assets/vanillasky-logo.svg +151 -0
  5. package/dist/{builtin-server-KB7FKF6A.js → builtin-server-CUYPIDE7.js} +2 -2
  6. package/dist/check-runtime.js +1 -1
  7. package/dist/{chunk-2PYO6VAC.js → chunk-2DOLF4QN.js} +1 -43
  8. package/dist/{chunk-GAIOHGNR.js → chunk-2OKB27TG.js} +42 -45
  9. package/dist/{chunk-K746NUIP.js → chunk-2USVB3CY.js} +80 -29
  10. package/dist/{chunk-RE4IMWJR.js → chunk-3VRMKFM7.js} +87 -14
  11. package/dist/{chunk-JNN3EYVP.js → chunk-4UNKZEAT.js} +46 -46
  12. package/dist/{chunk-2XT4MZ76.js → chunk-APQKY6P3.js} +36 -3
  13. package/dist/{chunk-LLPMVDJZ.js → chunk-L7QGGKJ2.js} +69 -38
  14. package/dist/{chunk-RGF452LL.js → chunk-OWBT45EN.js} +1 -1
  15. package/dist/{chunk-LKBZX7GV.js → chunk-PP3MCPN4.js} +4 -4
  16. package/dist/chunk-ZD2VTUYR.js +28 -0
  17. package/dist/cli.js +131 -24
  18. package/dist/{compose-video-PD6LKKRK.js → compose-video-2NFH4DZY.js} +3 -3
  19. package/dist/{events-B6qS1Lsb.d.ts → events-BQ6z264n.d.ts} +1 -1
  20. package/dist/index.d.ts +5 -67
  21. package/dist/index.js +2 -4
  22. package/dist/{kit-8g46H2RZ.d.ts → kit-tQnCPMOM.d.ts} +1 -1
  23. package/dist/react.d.ts +33 -53
  24. package/dist/react.js +982 -648
  25. package/dist/server.d.ts +11 -13
  26. package/dist/server.js +170 -81
  27. package/dist/template-catalog.js +1 -1
  28. package/dist/templates.d.ts +3 -3
  29. package/dist/test.d.ts +2 -2
  30. package/dist/test.js +3 -3
  31. package/dist/{text-stream-ROTNGSD4.js → text-stream-54LXABJW.js} +1 -1
  32. package/dist/{types-2wHBqtg8.d.ts → types-CEh9eUFu.d.ts} +1 -1
  33. package/dist/{types-DrABlRa7.d.ts → types-DWFO6qca.d.ts} +1 -1
  34. package/docs/agent-integration.md +9 -3
  35. package/docs/architecture.md +8 -10
  36. package/docs/concepts.md +16 -40
  37. package/docs/custom-templates.md +27 -23
  38. package/docs/customization.md +23 -55
  39. package/docs/errors.md +58 -68
  40. package/docs/getting-started.md +21 -14
  41. package/docs/immersive-interface.md +87 -0
  42. package/docs/media-and-audio.md +2 -2
  43. package/docs/performance.md +69 -0
  44. package/docs/persistence.md +12 -27
  45. package/docs/production.md +2 -2
  46. package/docs/provider-integration.md +11 -5
  47. package/docs/reference/design-system.html +115 -0
  48. package/docs/reference/provider-adapters.md +37 -89
  49. package/docs/security.md +1 -1
  50. package/docs/streaming-protocol.md +2 -2
  51. package/examples/custom-template/README.md +6 -6
  52. package/package.json +6 -7
  53. package/registry/items/barChart.json +2 -2
  54. package/registry/items/bigNumber.json +2 -2
  55. package/registry/items/brandMessage.json +2 -2
  56. package/registry/items/cardList.json +2 -2
  57. package/registry/items/codeEditor.json +2 -2
  58. package/registry/items/ctaLogo.json +2 -2
  59. package/registry/items/ctaMedia.json +2 -2
  60. package/registry/items/incomingCall.json +2 -2
  61. package/registry/items/media.json +2 -2
  62. package/registry/items/milestone.json +2 -2
  63. package/registry/items/notification.json +2 -2
  64. package/registry/items/phoneMockup.json +2 -2
  65. package/registry/items/problemSolution.json +2 -2
  66. package/registry/items/progressRing.json +2 -2
  67. package/registry/items/promptInput.json +2 -2
  68. package/registry/items/reaction.json +2 -2
  69. package/registry/items/reviewStack.json +2 -2
  70. package/registry/items/steps.json +2 -2
  71. package/registry/items/terminal.json +2 -2
  72. package/registry/items/testimonial.json +2 -2
  73. package/registry/items/tripleStats.json +2 -2
  74. package/registry/items/tweet.json +2 -2
  75. package/registry/items/webMockup.json +2 -2
  76. package/starters/video-chat/.env.example +4 -2
  77. package/starters/video-chat/README.md +17 -5
  78. package/starters/video-chat/index.html +2 -1
  79. package/starters/video-chat/package.json +2 -4
  80. package/starters/video-chat/providers/speech.ts +20 -0
  81. package/starters/video-chat/providers/video.ts +66 -0
  82. package/starters/video-chat/providers.ts +3 -0
  83. package/starters/video-chat/server.ts +4 -80
  84. package/starters/video-chat/stock.ts +114 -99
  85. package/styles/video-chat.css +650 -246
  86. package/dist/chunk-SKRGRKHY.js +0 -142
  87. package/dist/state-DZcKuS32.d.ts +0 -3
  88. package/docs/branding-and-personalization.md +0 -87
  89. package/examples/custom-template/supplied-media.tsx +0 -92
@@ -0,0 +1,87 @@
1
+ [← Documentation home](../README.md)
2
+
3
+ # Immersive video chat
4
+
5
+ `VideoChat` provides the complete conversation interface over an adaptive video
6
+ canvas. Import its stylesheet once; no copied example UI or component setup is
7
+ required.
8
+
9
+ ```tsx
10
+ import { VideoChat } from "@vanillaskyai/video/react";
11
+ import "@vanillaskyai/video/video-chat.css";
12
+
13
+ export function App() {
14
+ return <VideoChat options={{ endpoint: "/api/video-chat" }} />;
15
+ }
16
+ ```
17
+
18
+ The [interactive component reference](reference/design-system.html) uses the
19
+ same packaged stylesheet. It demonstrates navigation, settings, history,
20
+ conversation input, subtitles, suggestions and interaction states without
21
+ requesting a microphone or calling a model.
22
+
23
+ ## Watching and asking
24
+
25
+ The video owns the canvas. The navigation contains the VanillaSky logo, new
26
+ session, history, voice and settings. One floating field supports speech and
27
+ text; playback, microphone and send controls stay beside the question.
28
+
29
+ Beginning a question pauses the picture and narration together. Speech becomes
30
+ a draft to review. Sending begins the next answer; canceling returns to the
31
+ previous playback state. Canceling voice input also discards pending
32
+ transcription so a late result cannot replace a new draft.
33
+
34
+ The first subtitle hides the input unless editing, listening or keyboard focus
35
+ requires it. Pointer activity or touch reveals the controls again. They hide
36
+ after two seconds of inactivity during playback; paused playback and active
37
+ controls remain accessible. A stationary pointer left over Send does not hold
38
+ the input open. Settings can keep the input visible.
39
+
40
+ ## Subtitles and transcripts
41
+
42
+ Subtitles sit on a dark backing over the picture. The complete current cue
43
+ remains available without a line clamp or ellipsis. When the input appears,
44
+ subtitles move upward; when it disappears, they return to the bottom baseline.
45
+ The transition preserves space for both rows instead of abruptly repositioning
46
+ the subtitle.
47
+
48
+ Subtitle actions fade while inactive and return on hover, touch or keyboard
49
+ focus. Expand opens the answer transcript in the same surface. Hide removes
50
+ subtitles; the Subtitles switch in Settings restores them. The transcript is
51
+ part of the video interface rather than a separate modal.
52
+
53
+ ## Settings and history
54
+
55
+ Settings and history share one dark glass treatment. Watching preferences
56
+ control subtitles and input visibility. Video creation and style preferences
57
+ apply to the next question; provider capabilities determine available options.
58
+ History replays saved answers without generating them again. New session
59
+ retains up to ten sessions in memory, preserving completed answers for replay.
60
+ This history does not provide server or durable persistence; storage remains
61
+ application-owned. See [persistence](persistence.md).
62
+
63
+ Suggestions appear in a horizontal media-card rail. Pointer hover and keyboard
64
+ focus select a card; choosing it begins a follow-up answer. Focus outlines and
65
+ hover movement remain inside the rail's available space.
66
+
67
+ ## Layout and access
68
+
69
+ The foreground video preserves its scene ratio, so diagrams and text remain
70
+ visible without cropping or distortion. Ambient opening media fills the
71
+ surrounding viewport, with a gradient fallback when media is unavailable.
72
+ Display layout does not rewrite the saved response's orientation. See
73
+ [responsive orientation](responsive-orientation.md) for saved videos and custom
74
+ players.
75
+
76
+ Primary control targets are at least 44px. Bottom spacing includes the device
77
+ safe area. Keyboard focus stays visible, settings retain native switch and
78
+ radio behavior, and popovers support Escape and outside-click dismissal.
79
+ Reduced motion removes movement and fades; increased contrast strengthens
80
+ surface opacity and borders.
81
+
82
+ ## Branding
83
+
84
+ Use the existing `welcomeTitle`, `className` and `options` props to customize
85
+ copy, scoped CSS properties and generated video branding. There is no separate
86
+ light/dark appearance picker. See [customization](customization.md) for examples.
87
+ Use `useVideoChat` when the application needs to own the whole interface.
@@ -1,4 +1,4 @@
1
- [← Documentation home](../README.md) · [Previous: Branding and personalization](branding-and-personalization.md) · [Next: Custom templates →](custom-templates.md)
1
+ [← Documentation home](../README.md) · [Previous: Customization](customization.md) · [Next: Custom templates →](custom-templates.md)
2
2
 
3
3
  # Media, voice, and audio
4
4
 
@@ -132,4 +132,4 @@ interaction before audible playback on many devices.
132
132
  - Preload the next asset and keep the current visual when media is late.
133
133
  - Return a safe fallback instead of leaving the response waiting forever.
134
134
 
135
- [← Documentation home](../README.md) · [Previous: Branding and personalization](branding-and-personalization.md) · [Next: Custom templates →](custom-templates.md)
135
+ [← Documentation home](../README.md) · [Previous: Customization](customization.md) · [Next: Custom templates →](custom-templates.md)
@@ -0,0 +1,69 @@
1
+ # Video-chat performance
2
+
3
+ Measure the moment the response becomes visible and audible, and any wait for
4
+ its next scene. Attach local observations without changing the default UI:
5
+
6
+ ```tsx
7
+ import { VideoChat } from "@vanillaskyai/video/react";
8
+ import "@vanillaskyai/video/video-chat.css";
9
+
10
+ export function App() {
11
+ return <VideoChat options={{
12
+ onPlaybackMetric(metric) {
13
+ console.info(metric.type, metric.elapsedMs);
14
+ },
15
+ }} />;
16
+ }
17
+ ```
18
+
19
+ The SDK sends nothing to a telemetry service. Events contain only an opaque
20
+ turn ID, mode, relative timing, and fixed event categories. Keep custom turn IDs
21
+ opaque; do not put prompts or customer information into them.
22
+
23
+ ## What the measurements mean
24
+
25
+ `first-frame` is the first committed active scene reaching an animation-frame
26
+ opportunity. It excludes the generation cover and idle poster. It is not proof
27
+ of physical screen paint or decoded footage. The existing `onFirstFrame`
28
+ callback observes this same point.
29
+
30
+ `first-speech` comes from actual browser utterance start or generated audio
31
+ playback. It is not the time a speech request finishes. Custom voices must call
32
+ `onStart()` when sound begins; otherwise this measurement remains unavailable.
33
+ Muted responses do not produce a speech-start event.
34
+
35
+ `stall` measures a wait after the player reaches the end of its available scenes
36
+ while more scenes are being prepared. A completed interval includes `durationMs`.
37
+ Deliberate pauses are excluded. This does not measure network buffering inside
38
+ an image or video, because those assets do not control the scene clock.
39
+
40
+ Elapsed times start at prompt submission and can include user pauses. Compare
41
+ unpaused runs with the same mode and voice configuration. Treat missing speech
42
+ observations as missing data rather than zero milliseconds.
43
+
44
+ ## Reproducible checks
45
+
46
+ Run `npm run browser:test -- tests/browser/video-chat-performance.spec.ts` for
47
+ controlled local scenarios. They delay scene delivery, report speech onset from
48
+ a mock voice, verify pause exclusion, and attach the observed metrics as JSON.
49
+ These checks detect sequencing regressions. Their results are not live-provider
50
+ benchmarks and do not predict generated-video latency.
51
+
52
+ The initial fallback limits are 15 seconds for generated video and 3 seconds
53
+ for stock media, generated speech preparation, and fallback narration. Validate
54
+ these against an explicitly authorized, bounded live run before treating them
55
+ as tuned provider budgets. Compare first-frame/speech times, stalled duration,
56
+ and visual/voice quality together; faster fallback alone does not prove quality.
57
+
58
+ ## Opening stock footage
59
+
60
+ The opening's stock lookup runs alongside narration and body generation. Ready
61
+ footage stays behind the hook until the body starts; late results are ignored.
62
+ Playback never waits solely for intro footage.
63
+
64
+ The packaged stock adapter tries the specific and optional broader video query
65
+ before photo recovery, within one three-second budget. The planner supplies the
66
+ broader query only for opening atmosphere; body demonstrations retain their
67
+ specific subject. Pexels resource-page slugs and photo descriptions can screen
68
+ obvious mismatches, but missing metadata remains unknown and is accepted. This
69
+ is not visual relevance verification. See the [Pexels API contract](https://www.pexels.com/api/documentation/).
@@ -3,9 +3,12 @@
3
3
  # Persistence and replay
4
4
 
5
5
  A completed `Video` is ordinary JSON owned by your application. VanillaSky
6
- does not provide a database or hosted media store. Save the value returned by
7
- `await video.generate(...)` with the platform-native `JSON.stringify`; there is
8
- no SDK serializer.
6
+ does not provide a database or hosted media store. For a custom interface, observe `useVideoChat().turns` and save a turn’s
7
+ `video` only when `turn.completed` is true and `turn.video` is present. Use
8
+ `JSON.stringify(turn.video)` and deduplicate writes by `turn.id`; there is no
9
+ SDK serializer. An interrupted turn can remain visible without qualifying as
10
+ completed conversation history. The default `VideoChat` keeps history in memory;
11
+ use the headless hook when the application needs durable storage.
9
12
 
10
13
  Every stored video has `schemaVersion: "0.1"`. This storage version is separate
11
14
  from streaming protocol `0.5`. The 0.1 policy supports the current storage
@@ -48,31 +51,13 @@ runs; it never renders a partial future document.
48
51
 
49
52
  ## Retention
50
53
 
51
- By default, completed snapshots omit raw source, creative instructions, and
52
- the supplied-media URL index. A customer-owned route may retain individual
53
- fields only when its privacy and deletion policy allows it:
54
-
55
- ```ts
56
- createVideoHandler({
57
- authorize: verifySession,
58
- streamText,
59
- snapshotRetention: {
60
- source: true,
61
- instructions: true,
62
- suppliedMediaUrls: true,
63
- },
64
- });
65
- ```
66
-
67
- Opt-in values are bounded in the snapshot:
68
-
69
- - source: 16,384 characters;
70
- - instructions: 4,096 characters;
71
- - supplied-media index: 16 URLs, each at most 2,048 characters.
54
+ Completed snapshots omit raw source, creative instructions, and the supplied-media
55
+ URL index. Store an authorized prompt separately with the completed turn only
56
+ when the host's privacy and deletion policy permits it. Saved-video replay does
57
+ not rehydrate a chat session or its voice queue.
72
58
 
73
- These metadata limits do not replace a host retention policy. Renderable scene
74
- variables may still contain a media URL when that asset is necessary for
75
- replay. Store only approved assets and avoid signed URLs whose lifetime is
59
+ Renderable scene variables may contain a media URL when that asset is necessary
60
+ for replay. Store only approved assets and avoid signed URLs whose lifetime is
76
61
  shorter than the replay window.
77
62
 
78
63
  ## Storage ownership
@@ -59,7 +59,7 @@ can begin while the planner streams later scenes.
59
59
  - Treat late media as a fallback case, not a reason to freeze playback.
60
60
  - Keep the current scene and its narration during recoverable generation gaps.
61
61
  - End cleanly on a terminal error and show an application retry control.
62
- - Retry only before visible output or from an explicit validated resume point.
62
+ - Retry only before visible output; preserve accepted scenes after playback starts.
63
63
 
64
64
  ## Measure the stages
65
65
 
@@ -106,6 +106,6 @@ npm test
106
106
  - [ ] Both orientations render and narration stays synchronized.
107
107
  - [ ] A packed-artifact consumer and deterministic browser chat pass.
108
108
  - [ ] One bounded real-provider run meets the product's latency and quality target.
109
- - [ ] Stored responses replay exactly and application-owned export is verified.
109
+ - [ ] Completed stored responses parse and replay correctly.
110
110
 
111
111
  [← Documentation home](../README.md) · [Previous: Errors and recovery](errors.md)
@@ -1,4 +1,4 @@
1
- [← Documentation home](../README.md) · [Previous: Getting started](getting-started.md) · [Next: Branding and personalization →](branding-and-personalization.md)
1
+ [← Documentation home](../README.md) · [Previous: Getting started](getting-started.md) · [Next: Customization →](customization.md)
2
2
 
3
3
  # Provider integration
4
4
 
@@ -11,10 +11,16 @@ npx vanillasky doctor
11
11
  npm run dev
12
12
  ```
13
13
 
14
- The generated `server.ts` is the canonical provider example. It starts with one
15
- text key, packaged templates, and browser voice. Adding the optional generated
16
- speech, stock, transcription, or generated-video key enables its callback and
17
- advertises the capability automatically; `src/main.tsx` does not change.
14
+ Init runs doctor automatically. The generated `server.ts` starts with one
15
+ `ANTHROPIC_API_KEY`, packaged templates, and browser voice; it installs no
16
+ optional speech or video packages.
17
+
18
+ Use `npx vanillasky providers add speech` to install xAI speech, or
19
+ `npx vanillasky providers add video` to install FAL video and transcription.
20
+ Add `XAI_API_KEY` or `FAL_KEY` to `.env.local` and restart the server. Stock media
21
+ needs only `PEXELS_API_KEY`, with no extra installation. These app-owned
22
+ adapters advertise their capabilities automatically; `src/main.tsx` does not
23
+ change. Rerun an interrupted setup command to finish installation.
18
24
 
19
25
  For the full chat experience, mount one `createVideoChatHandler` and keep every
20
26
  provider choice in its callbacks:
@@ -0,0 +1,115 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">
5
+ <title>VanillaSky · Immersive design system</title>
6
+ <link rel="stylesheet" href="../../styles/video-chat.css">
7
+ <style>
8
+ html { scroll-behavior: smooth; color-scheme: dark; }
9
+ body { background: #080b16; }
10
+ .vanillasky-video-chat.docs { height: auto; min-height: 100dvh; overflow: visible; padding: 0 40px 64px; }
11
+ .docs .doc-wrap { max-width: 1180px; margin: auto; }
12
+ .docs .doc-header { display: flex; align-items: center; justify-content: space-between; gap: 24px; padding: 28px 0; border-bottom: 1px solid var(--vs-media-edge); }
13
+ .docs .doc-header img { width: 144px; height: 36px; }
14
+ .docs a { color: #c7c9ec; text-decoration: none; }
15
+ .docs .doc-link { display: inline-flex; align-items: center; gap: 10px; padding: 12px 16px; border: 1px solid var(--vs-media-edge); border-radius: 99px; font-size: 13px; }
16
+ .docs .doc-link:hover { background: var(--vs-media-hover); }
17
+ .docs .doc-intro { padding: 82px 0 48px; max-width: 780px; }
18
+ .docs .doc-kicker { color: #a4a9c5; font-size: 11px; font-weight: 600; letter-spacing: .13em; text-transform: uppercase; }
19
+ .docs .doc-intro h1 { font-size: clamp(38px, 5.5vw, 70px); font-weight: 500; letter-spacing: -.055em; line-height: 1.05; margin: 18px 0 24px; }
20
+ .docs .doc-intro h1 span { color: #b8bddc; }
21
+ .docs .doc-lede { font-size: 18px; line-height: 1.65; color: #adb3c9; max-width: 630px; }
22
+ .docs .doc-index { display: flex; gap: 24px; flex-wrap: wrap; padding-bottom: 26px; font-size: 13px; }
23
+ .docs .doc-section { padding: 42px 0 8px; scroll-margin-top: 24px; }
24
+ .docs .section-heading { display: flex; align-items: baseline; gap: 18px; margin-bottom: 18px; }
25
+ .docs .section-heading .number { color: #727b9b; font-size: 12px; font-variant-numeric: tabular-nums; }
26
+ .docs .section-heading h2 { margin: 0; font-size: 25px; font-weight: 500; letter-spacing: -.035em; }
27
+ .docs .section-copy { margin: 0 0 24px 36px; font-size: 14px; line-height: 1.7; color: #aab1c7; max-width: 710px; }
28
+ .docs .doc-preview { position: relative; padding: 28px; border: 1px solid var(--vs-media-edge); border-radius: 24px; overflow: hidden; background: radial-gradient(ellipse at 75% 0%, #31394d 0%, #171d30 35%, #0e1221 75%); }
29
+ .docs .doc-preview .chrome { position: relative; inset: auto; padding: 0; background: none; width: 100%; }
30
+ .docs .doc-note { color: #8e97b2; font-size: 12px; line-height: 1.65; margin: 16px 0 0; }
31
+ .docs .surface-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin-top: 20px; }
32
+ .docs .surface { border: 1px solid var(--vs-media-edge); min-height: 108px; border-radius: 16px; padding: 20px; display: flex; flex-direction: column; justify-content: space-between; gap: 14px; }
33
+ .docs .surface strong { font-size: 13px; font-weight: 500; }
34
+ .docs .surface code { font-size: 11px; color: #a8aec7; }
35
+ .docs .doc-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; align-items: start; }
36
+ .docs .doc-preview .sheet-popover { position: relative; inset: auto; transform: none; width: 100%; max-width: none; max-height: none; margin: 0; animation: none; }
37
+ .docs .doc-preview.popover-demo { padding: 24px; }
38
+ .docs .demo-label { display: block; margin: 0 0 16px; color: #8e97b2; font-size: 11px; letter-spacing: .1em; text-transform: uppercase; }
39
+ .docs .doc-stack { display: flex; flex-direction: column; gap: 24px; }
40
+ .docs .doc-preview .conversation-composer { margin: auto; }
41
+ .docs .doc-preview .line-row { width: min(680px, 100%); margin: auto; }
42
+ .docs .doc-preview .expanded-captions { max-height: 220px; }
43
+ .docs .demo-toolbar { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 24px; }
44
+ .docs .demo-toolbar button { min-height: 36px; padding: 8px 14px; border-radius: 99px; border: 1px solid var(--vs-media-edge); background: var(--vs-media-glass); color: var(--vs-media-muted); font: inherit; font-size: 12px; cursor: pointer; }
45
+ .docs .demo-toolbar button[aria-pressed="true"] { color: white; background: var(--vs-media-selected); }
46
+ .docs [hidden] { display: none !important; }
47
+ .docs .cards { margin: 0; width: 100%; max-width: 100%; }
48
+ .docs .cards li { flex: 1; }
49
+ .docs .cards button { width: 100%; min-width: 180px; }
50
+ .docs .card-art { position: absolute; inset: 0; background: radial-gradient(ellipse at 70% 30%, #658398, transparent 60%), linear-gradient(140deg, #172b49, #101724); }
51
+ .docs .card-art.space { background: radial-gradient(circle at 64% 36%, #b5a590 0, #786786 10%, transparent 27%), linear-gradient(120deg, #1e203e, #0b1525); }
52
+ .docs .card-art.mind { background: radial-gradient(ellipse at 45% 20%, #8d6477, transparent 60%), linear-gradient(130deg, #38334f, #141827); }
53
+ .docs .type-row { display: flex; align-items: baseline; justify-content: space-between; gap: 24px; padding: 22px 0; border-bottom: 1px solid var(--vs-media-edge); }
54
+ .docs .type-row code { flex-shrink: 0; font-size: 11px; color: #8e97b2; }
55
+ .docs .metrics { display: grid; grid-template-columns: repeat(4, 1fr); gap: 22px; margin-top: 28px; }
56
+ .docs .metric strong { display: block; font-size: 32px; font-weight: 400; letter-spacing: -.04em; }
57
+ .docs .metric span { display: block; color: #9ba4bd; font-size: 12px; line-height: 1.6; margin-top: 10px; }
58
+ .docs .doc-footer { margin-top: 58px; padding-top: 22px; border-top: 1px solid var(--vs-media-edge); color: #808ba8; font-size: 12px; display: flex; justify-content: space-between; gap: 20px; }
59
+ @media (max-width: 800px) { .vanillasky-video-chat.docs { padding: 0 20px 40px; } .docs .doc-intro { padding-top: 54px; } .docs .doc-grid { grid-template-columns: 1fr; } .docs .surface-grid,.docs .metrics { grid-template-columns: 1fr 1fr; } .docs .doc-preview { padding: 20px; } .docs .doc-preview .chrome { flex-wrap: wrap; gap: 18px; } .docs .doc-preview .chrome .session-brand { flex-basis: 100%; } .docs .doc-preview .chrome > .group:first-of-type { margin-left: 0; } .docs .type-row { align-items: flex-start; flex-direction: column; gap: 12px; } .docs .section-copy { margin-left: 0; } }
60
+ @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
61
+ </style>
62
+ </head>
63
+ <body>
64
+ <svg xmlns="http://www.w3.org/2000/svg" style="position:absolute;width:0;height:0;overflow:hidden" aria-hidden="true"><defs>
65
+ <symbol id="plus" viewBox="0 0 24 24"><path d="M12 5v14M5 12h14" /></symbol>
66
+ <symbol id="history" viewBox="0 0 24 24"><path d="M3 11a9 9 0 1 1 2.6 7M3 4v7h7M12 7v5l3 2" /></symbol>
67
+ <symbol id="sound" viewBox="0 0 24 24">
68
+ <path d="M11 5 6 9H2v6h4l5 4z" />
69
+ <path d="M15.5 8.5a5 5 0 0 1 0 7M18.5 5.5a9 9 0 0 1 0 13" />
70
+ </symbol>
71
+ <symbol id="settings" viewBox="0 0 24 24">
72
+ <circle cx="12" cy="12" r="3" />
73
+ <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.6a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1Z" />
74
+ </symbol>
75
+ <symbol id="close" viewBox="0 0 24 24"><path d="M6 6l12 12M18 6 6 18" /></symbol>
76
+ <symbol id="mic" viewBox="0 0 24 24">
77
+ <rect x="9" y="2" width="6" height="12" rx="3" />
78
+ <path d="M5 11a7 7 0 0 0 14 0M12 18v4" />
79
+ </symbol>
80
+ <symbol id="send" viewBox="0 0 24 24"><path d="M12 19V5M5 12l7-7 7 7" /></symbol>
81
+ <symbol id="play" viewBox="0 0 24 24"><path d="m8 5 11 7-11 7z"/></symbol>
82
+ <symbol id="up" viewBox="0 0 24 24"><path d="m6 15 6-6 6 6"/></symbol>
83
+ </defs></svg>
84
+ <main class="vanillasky-video-chat docs" data-controls-visible="true"><div class="doc-wrap">
85
+ <header class="doc-header"><img src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDI4LjEuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHZpZXdCb3g9IjE1NSAxMTMgMTY5MCA0MjIiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMTU1IDExMyAxNjkwIDQyMjsiIHhtbDpzcGFjZT0icHJlc2VydmUiPgo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPgoJLnN0MHtmaWxsOnVybCgjU1ZHSURfMV8pO30KCS5zdDF7ZmlsbDp1cmwoI1NWR0lEXzAwMDAwMDEzMTc5MjQ3NzkzMzEzNjczNjYwMDAwMDA5NTAyNDY0NTI0MDQ3MTc5Njg2Xyk7fQoJLnN0MntmaWxsOnVybCgjU1ZHSURfMDAwMDAxMTQwNzU2MTAxNzA2MjA3NDYzMDAwMDAwMTMwNzY4NTczMjc1MDMwNTk4NTJfKTt9Cgkuc3Qze2ZpbGw6dXJsKCNTVkdJRF8wMDAwMDAzOTg0Mzk1Mzc4NTIyOTI0Mjg4MDAwMDAwODQwMzMzMzkyMDEyMjcwNTMyOF8pO30KCS5zdDR7ZmlsbDp1cmwoI1NWR0lEXzAwMDAwMDI3NTkyNTEzNTc2NDg3NDgzMzAwMDAwMDE2NzQwODQ2NzM4OTM4NjE5NzkyXyk7fQoJLnN0NXtmaWxsOnVybCgjU1ZHSURfMDAwMDAwNzM2ODI1Njc2NTkxMzUzNzk0NjAwMDAwMDQyOTE4NTk2MTM4MzIzNjcyNDZfKTt9Cgkuc3Q2e2ZpbGw6dXJsKCNTVkdJRF8wMDAwMDA0MzQyOTI4Mzg1Nzk2OTQ0NDE5MDAwMDAwNzg0MjM5Nzg0MTEwMTYxNjAxN18pO30KCS5zdDd7ZmlsbDojRkZGRkZGO30KPC9zdHlsZT4KPGc+Cgk8Zz4KCQk8Zz4KCQkJCgkJCQk8bGluZWFyR3JhZGllbnQgaWQ9IlNWR0lEXzFfIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjE0NC43Mzg4IiB5MT0iMzYxLjU0MjIiIHgyPSIxMTQ1LjM4NjYiIHkyPSIzMDguNTkwNyIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgxIDAgMCAtMSAwIDY1MCkiPgoJCQkJPHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6I0UwNEY4QSIvPgoJCQkJPHN0b3AgIG9mZnNldD0iMSIgc3R5bGU9InN0b3AtY29sb3I6I0VDOUEyQyIvPgoJCQk8L2xpbmVhckdyYWRpZW50PgoJCQk8cGF0aCBjbGFzcz0ic3QwIiBkPSJNNDMxLjkzLDI5OC42N2MtMC42Mi0wLjYtMS4zNi0xLjExLTIuMTktMS41N2MtMi40Mi0xLjMyLTUuNjQtMS45OC05LjctMS45OAoJCQkJYy0xNi4xMiwwLTMwLjQ0LTEuMDYtNDIuOTctMy4xOWMxMS44My0zMi4yLDE3Ljc2LTYxLjkyLDE3Ljc2LTg5LjE1YzAtMTguOTMtNC40NS0zMy44NC0xMy4zMi00NC43NAoJCQkJYy04Ljg5LTEwLjg3LTIwLjg5LTE2LjMyLTM2LjA1LTE2LjMyYy0xMi4zMiwwLTIzLjUsMy4xOS0zMy41NSw5LjU5Yy0xMC4wOCw2LjQtMTgsMTYuMDQtMjMuOCwyOC45NQoJCQkJYy01LjgxLDEyLjg5LTguNywyOC43LTguNyw0Ny40MWMwLDE4LjcsMy42NiwzNS4yMSwxMSw0OS41NGM3LjM0LDE0LjMyLDE4LjIzLDI1Ljk5LDMyLjY3LDM0Ljk3CgkJCQljLTEyLjA2LDI1LjgyLTI1LjMzLDQ3LjI0LTM5Ljc2LDY0LjI4Yy0xNC40NiwxNy4wNi0yNy44MiwyNS41Ny00MC4xNCwyNS41N2MtMTIuMDYsMC0yMS4xMi05LjQtMjcuMTYtMjguMjMKCQkJCWMtNi4wNC0xOC44Mi05LjA2LTQ2LjMzLTkuMDYtODIuNTZjMC0zNC41NSwzLjU1LTczLjE1LDEwLjY2LTExNS43NmMwLjQ3LTMuNzksMC43LTYuNCwwLjctNy44MWMwLTEzLjUxLTcuODEtMjAuMjUtMjMuNDQtMjAuMjUKCQkJCWMtOS40NywwLTE2LjE1LDIuMTktMjAuMDYsNi41N3MtNi45MywxMi43NC05LjA2LDI1LjA0Yy01LjkzLDMzLjE0LTguODcsNzAuNTQtOC44NywxMTIuMjFjMCw0OC43OCw2LjA0LDg3LjQ5LDE4LjEsMTE2LjEyCgkJCQljMTIuMDgsMjguNjcsMzAuNDIsNDIuOTcsNTUuMDUsNDIuOTdjMjMuOTEsMCw0Ny43Ni0xMS42NCw3MS41Ni0zNC45N2MyMy44LTIzLjMzLDQ0LjA4LTUyLjYxLDYwLjktODcuODkKCQkJCWMxMC42MSwyLjQsMjIuMzMsMy43OSwzNS4xNCw0LjIxYzQuOTMsMC4xNywxMC4wMiwwLjE3LDE1LjI5LDAuMDRjNy44MS0wLjIzLDEzLjU1LTIuNzIsMTcuMjMtNy40NQoJCQkJYzMuNjYtNC43NCw1LjUxLTEwLjE3LDUuNTEtMTYuMzJDNDM1LjY3LDMwNC4xMiw0MzQuNDIsMzAxLjA0LDQzMS45MywyOTguNjd6IE0zMzcuNjUsMjc2LjY2CgkJCQljLTE0LjkxLTExLjEzLTIyLjM4LTI4LjI5LTIyLjM4LTUxLjVjMC0xMy43MiwyLjAyLTI0LjMzLDYuMDQtMzEuNzhjNC4wNC03LjQ1LDkuMjUtMTEuMTksMTUuNjMtMTEuMTkKCQkJCWM0LjQ5LDAsOC4wNiwyLjMsMTAuNjYsNi45M2MyLjYsNC42MiwzLjkxLDExLjg5LDMuOTEsMjEuODNDMzUxLjUsMjI4LjI0LDM0Ni44NywyNTAuMTUsMzM3LjY1LDI3Ni42NnoiLz4KCQkJCgkJCQk8bGluZWFyR3JhZGllbnQgaWQ9IlNWR0lEXzAwMDAwMDg5NTUyODM1Mzg3NjQwNjA5ODkwMDAwMDA0ODExOTA0NjIyNjQ2MDYyNzMyXyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIHgxPSIxMzcuMjUzNSIgeTE9IjMwOC44OTY2IiB4Mj0iMTEzNy45MDE0IiB5Mj0iMjU1Ljk0NTEiIGdyYWRpZW50VHJhbnNmb3JtPSJtYXRyaXgoMSAwIDAgLTEgMCA2NTApIj4KCQkJCTxzdG9wICBvZmZzZXQ9IjAiIHN0eWxlPSJzdG9wLWNvbG9yOiNFMDRGOEEiLz4KCQkJCTxzdG9wICBvZmZzZXQ9IjEiIHN0eWxlPSJzdG9wLWNvbG9yOiNFQzlBMkMiLz4KCQkJPC9saW5lYXJHcmFkaWVudD4KCQkJPHBhdGggc3R5bGU9ImZpbGw6dXJsKCNTVkdJRF8wMDAwMDA4OTU1MjgzNTM4NzY0MDYwOTg5MDAwMDAwNDgxMTkwNDYyMjY0NjA2MjczMl8pOyIgZD0iTTc0Ny45LDM3My42MQoJCQkJYy0xLjc3LTIuODUtNC4yMS00LjI3LTcuMjgtNC4yN2MtMy41NSwwLTYuNzQsMS42Ni05LjU5LDQuOTZjLTQuMSw0LjkxLTcuODcsOS4yNy0xMS4zMiwxMy4xM2MtNS43Nyw2LjQ1LTEwLjcsMTEuNDctMTQuNzgsMTUuMQoJCQkJYy02LjUxLDUuODEtMTIuMTMsOC43LTE2Ljg3LDguN2MtNi44NywwLTEwLjMtNC43Mi0xMC4zLTE0LjE5YzAtNi42MiwyLjI2LTIwLjI1LDYuNzYtNDAuODRjNS4yMS0yNC4xNiw3LjgxLTQwLjg0LDcuODEtNTAuMDkKCQkJCWMwLTE1LjM4LTcuNy0yMy4wOC0yMy4wOC0yMy4wOGMtNy44MSwwLTE2LjQsMi43NC0yNS43NCw4LjE3Yy05LjM2LDUuNDUtMTguODksMTQuNTctMjguNTksMjcuMzUKCQkJCWMtOS43MiwxMi43OC0xOC40OCwyOS4zNi0yNi4yOSw0OS43MWMwLjk0LTEwLjQsMi4xMy0xOS4xNywzLjU1LTI2LjI3YzEuNDMtNy4xLDMuMzItMTUuMzgsNS43LTI0Ljg1CgkJCQljMy41NS0xMy4yNyw1LjMyLTIxLjc4LDUuMzItMjUuNTdjMC0zLjMyLTAuOTYtNS41Ny0yLjg1LTYuNzZjLTEuODktMS4xNy01LjIxLTEuNzctOS45NS0xLjc3Yy04Ljc2LDAtMTUuNTcsMS42LTIwLjQyLDQuNzkKCQkJCWMtNC44NSwzLjIxLTguMzQsOC4yMy0xMC40NywxNS4xYy04LjM0LDI2LjM4LTEyLjcsNTQuMTYtMTMuMSw4My4zNGMtMC4wMiwxLjQ1LTAuMDQsMi45MS0wLjA0LDQuMzhjMCwxNiwxLjA4LDI4LjY3LDMuMjYsMzcuOTcKCQkJCWMwLjY0LDIuNzksMS40LDUuMywyLjI1LDcuNDljMy42Niw5LjQ3LDkuOTgsMTQuMTksMTguOTgsMTQuMTljNy4zNCwwLDEyLjc0LTEuOTQsMTYuMTctNS44NWMzLjQyLTMuOTEsNi40NC0xMS40Miw5LjA0LTIyLjU1CgkJCQljMy41Ny0xNC40NCw4LjIzLTI4LjE4LDE0LjA0LTQxLjJjNS43OS0xMy4wMiwxMS40Ny0yMy41LDE3LjA0LTMxLjQyYzUuNTctNy45Myw5Ljg5LTExLjkxLDEyLjk2LTExLjkxCgkJCQljMi42LDAsMy45MSwxLjkxLDMuOTEsNS42OGMwLDUuNy0xLjU1LDE1Ljk4LTQuNjIsMzAuOTFjLTMuMzIsMTcuMDQtNC45NiwyOC44Ny00Ljk2LDM1LjVjMCwxMy4yNywzLjA4LDIzLjM4LDkuMjMsMzAuMzYKCQkJCWM2LjE1LDYuOTgsMTUuMjcsMTAuNDcsMjcuMzUsMTAuNDdjMTQuOTEsMCwyOC4yMy00LjAyLDM5Ljk1LTEyLjA2YzUuMTctMy41NywxMC4xOS03LjU1LDE1LjA4LTExLjk2CgkJCQljNi4xNS01LjYyLDEyLjA4LTExLjkzLDE3Ljc4LTE4Ljk1YzQuNDktNS4xOSw2Ljc0LTEyLjUzLDYuNzQtMjJDNzUwLjU2LDM4MC4zNCw3NDkuNjcsMzc2LjQ0LDc0Ny45LDM3My42MXoiLz4KCQkJCgkJCQk8bGluZWFyR3JhZGllbnQgaWQ9IlNWR0lEXzAwMDAwMDM2OTY2Mjg4NDUyMDI4MTAzOTgwMDAwMDA2MTQ5NTUyMTE1MTU0NzIxOTQ4XyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIHgxPSIxMzkuNzQyOCIgeTE9IjM1NS45MzgyIiB4Mj0iMTE0MC4zOTA3IiB5Mj0iMzAyLjk4NjciIGdyYWRpZW50VHJhbnNmb3JtPSJtYXRyaXgoMSAwIDAgLTEgMCA2NTApIj4KCQkJCTxzdG9wICBvZmZzZXQ9IjAiIHN0eWxlPSJzdG9wLWNvbG9yOiNFMDRGOEEiLz4KCQkJCTxzdG9wICBvZmZzZXQ9IjEiIHN0eWxlPSJzdG9wLWNvbG9yOiNFQzlBMkMiLz4KCQkJPC9saW5lYXJHcmFkaWVudD4KCQkJPHBhdGggc3R5bGU9ImZpbGw6dXJsKCNTVkdJRF8wMDAwMDAzNjk2NjI4ODQ1MjAyODEwMzk4MDAwMDAwNjE0OTU1MjExNTE1NDcyMTk0OF8pOyIgZD0iTTgzMy40OCwzNzMuNjEKCQkJCWMtMS43Ny0yLjg1LTQuMjEtNC4yNy03LjI4LTQuMjdjLTMuNTUsMC02Ljc2LDEuNjYtOS41OSw0Ljk2Yy0yLjEzLDIuNTctNC4xNyw0Ljk4LTYuMTMsNy4yN2MtNy44NSw5LjEzLTE0LjMyLDE2LjA4LTE5LjQ0LDIwLjgKCQkJCWMtNi40LDUuOTMtMTEuNzIsOC44Ny0xNS45OCw4Ljg3Yy00LjQ5LDAtNy43LTEuODktOS41OS01LjY4Yy0xLjg5LTMuNzctMi44My05LjIzLTIuODMtMTYuMzJjMC05LjI1LDIuODMtMjYuODcsOC41MS01Mi45MgoJCQkJYzQuNDktMjEuNTMsNi43Ni0zNS4yNyw2Ljc2LTQxLjJjMC04LjA0LTYuMDQtMTIuMDgtMTguMTItMTIuMDhjLTcuODEsMC0xMy40OSwxLjQzLTE3LjA0LDQuMjdjLTMuNTUsMi44NS02LjQsOC4wNi04LjUzLDE1LjYzCgkJCQljLTQuMjcsMTQuNDQtNy43NiwzMC4wMS0xMC40Nyw0Ni43MWMtMi40NSwxNS4wNi0zLjc5LDI3LjY1LTQuMDQsMzcuOGMtMC4wMiwxLjA5LTAuMDQsMi4xNy0wLjA0LDMuMjEKCQkJCWMwLDE0LjA0LDIuMTMsMjUuOTEsNi4zOCwzNS42M2MxLjE5LDIuNzQsMi41Nyw1LjMsNC4xLDcuN2M2Ljk4LDEwLjg5LDE4LjE1LDE2LjMyLDMzLjU1LDE2LjMyYzE3Ljg3LDAsMzYuOTEtMTEuMDIsNTcuMTYtMzMuMQoJCQkJYzIuODEtMy4wOCw1LjY2LTYuMzYsOC41My05Ljg3YzQuNTEtNS4xOSw2Ljc2LTEyLjUzLDYuNzYtMjJDODM2LjE0LDM4MC4zNCw4MzUuMjYsMzc2LjQ0LDgzMy40OCwzNzMuNjF6IE03OTIuMTIsMjEwLjYxCgkJCQljLTUuNDUtNC4yNy0xMi41Ny02LjQtMjEuMzItNi40Yy05LjcsMC0xNy44MiwyLjc3LTI0LjMzLDguMzRjLTYuNTEsNS41Ny05Ljc2LDEyLjQ5LTkuNzYsMjAuNzhjMCw4LjI4LDIuNDksMTQuNzQsNy40NSwxOS4zNAoJCQkJYzQuOTgsNC42MiwxMi40NCw2LjkzLDIyLjM4LDYuOTNjMTAuMTcsMCwxOC4zNC0yLjc3LDI0LjUtOC4zNGM2LjE1LTUuNTUsOS4yMy0xMy4wOCw5LjIzLTIyLjU1CgkJCQlDODAwLjI3LDIyMC45LDc5Ny41NSwyMTQuODYsNzkyLjEyLDIxMC42MXoiLz4KCQkJCgkJCQk8bGluZWFyR3JhZGllbnQgaWQ9IlNWR0lEXzAwMDAwMTY5NTQ0MDU3OTMxOTgyMTQwNjIwMDAwMDAzNjMwOTA4MjUzMDQ2NjA0NDcxXyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIHgxPSIxNDIuNDM4MiIgeTE9IjQwNi44NzQ3IiB4Mj0iMTE0My4wODYxIiB5Mj0iMzUzLjkyMzIiIGdyYWRpZW50VHJhbnNmb3JtPSJtYXRyaXgoMSAwIDAgLTEgMCA2NTApIj4KCQkJCTxzdG9wICBvZmZzZXQ9IjAiIHN0eWxlPSJzdG9wLWNvbG9yOiNFMDRGOEEiLz4KCQkJCTxzdG9wICBvZmZzZXQ9IjEiIHN0eWxlPSJzdG9wLWNvbG9yOiNFQzlBMkMiLz4KCQkJPC9saW5lYXJHcmFkaWVudD4KCQkJPHBhdGggc3R5bGU9ImZpbGw6dXJsKCNTVkdJRF8wMDAwMDE2OTU0NDA1NzkzMTk4MjE0MDYyMDAwMDAwMzYzMDkwODI1MzA0NjYwNDQ3MV8pOyIgZD0iTTk0Ny40NywzNzMuNjEKCQkJCWMtMS43Ny0yLjg1LTQuMjEtNC4yNy03LjI4LTQuMjdjLTMuNTUsMC02Ljc0LDEuNjYtOS41OSw0Ljk2Yy0yLjExLDIuNTMtNC4xNyw0LjkxLTYuMTUsNy4xMwoJCQkJYy04LjYyLDkuNzktMTUuOTMsMTYuOTUtMjEuODksMjEuNDZjLTcuMzQsNS41Ny0xNS44Nyw4LjM0LTI1LjU3LDguMzRjLTYuMTcsMC0xMS4xMy0yLjA2LTE0LjkzLTYuMjEKCQkJCWMtMy43OS00LjEzLTYuNTEtMTEuMDYtOC4xNy0yMC43OGMyNi43Ni0zNi40NCw0Ny45NS03My4yNiw2My41OC0xMTAuNDRjMTUuNjMtMzcuMTYsMjMuNDQtNjkuODQsMjMuNDQtOTguMDIKCQkJCWMwLTE5LjY1LTMuMjYtMzQuNzQtOS43OC00NS4yN2MtNi41MS0xMC41My0xNS40NC0xNS44LTI2LjgtMTUuOGMtMjAuMTQsMC0zNy40OCwxMy4yNS01Mi4wMywzOS43NgoJCQkJYy0xNC41NywyNi41MS0yNS41Nyw1OC4yNC0zMy4wMyw5NS4xN2MtNy40NSwzNi45My0xMS4xOSw2OS44NC0xMS4xOSw5OC43NGMwLDExLjk1LDAuNzksMjMsMi40LDMzLjE4CgkJCQljMi4wNiwxMy40LDUuNTMsMjUuMjcsMTAuMzgsMzUuNjNjMC43NCwxLjYsMS41MSwzLjE3LDIuMzIsNC43YzEwLjA2LDE4Ljk1LDI1LjUsMjguNCw0Ni4zNSwyOC40CgkJCQljMTUuMTQsMCwyOC42OS00LjAyLDQwLjY1LTEyLjA2YzguNjgtNS44NSwxNi44OS0xMi44NywyNC42NS0yMS4xYzIuOTEtMy4wOSw1Ljc3LTYuMzgsOC41Ny05LjgxYzQuNDktNS4xOSw2Ljc0LTEyLjUzLDYuNzQtMjIKCQkJCUM5NTAuMTMsMzgwLjM0LDk0OS4yNCwzNzYuNDQsOTQ3LjQ3LDM3My42MXogTTg1OS45MiwyNTIuNTFjNS4yMS0yOS4xMiwxMS4yNS01My41LDE4LjEyLTczLjE1CgkJCQljNi44Ny0xOS42NiwxMy4wMi0yOS40OCwxOC40OC0yOS40OGM2LjYyLDAsOS45NSw5LDkuOTUsMjYuOTljMCwyMi45Ny00Ljk4LDQ4LjM1LTE0LjkzLDc2LjE3cy0yMy4zMyw1NS41OC00MC4xMiw4My4yOAoJCQkJQzg1MS44OCwzMDkuNTUsODU0LjcxLDI4MS42Miw4NTkuOTIsMjUyLjUxeiIvPgoJCQkKCQkJCTxsaW5lYXJHcmFkaWVudCBpZD0iU1ZHSURfMDAwMDAwOTYwMzk0OTc1NDgzNzkyMzk0NjAwMDAwMTc2ODAwODc0NTg3MzgyMjU1NjVfIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjE0Mi43NTY1IiB5MT0iNDEyLjg4ODMiIHgyPSIxMTQzLjQwNDMiIHkyPSIzNTkuOTM2OCIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgxIDAgMCAtMSAwIDY1MCkiPgoJCQkJPHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6I0UwNEY4QSIvPgoJCQkJPHN0b3AgIG9mZnNldD0iMSIgc3R5bGU9InN0b3AtY29sb3I6I0VDOUEyQyIvPgoJCQk8L2xpbmVhckdyYWRpZW50PgoJCQk8cGF0aCBzdHlsZT0iZmlsbDp1cmwoI1NWR0lEXzAwMDAwMDk2MDM5NDk3NTQ4Mzc5MjM5NDYwMDAwMDE3NjgwMDg3NDU4NzM4MjI1NTY1Xyk7IiBkPSJNMTA2MS40NSwzNzMuNjEKCQkJCWMtMS43Ny0yLjg1LTQuMjEtNC4yNy03LjI3LTQuMjdjLTMuNTcsMC02Ljc2LDEuNjYtOS42MSw0Ljk2Yy03LjE3LDguNTMtMTMuNTUsMTUuNDctMTkuMTIsMjAuODMKCQkJCWMtMy4yNSwzLjEzLTYuMjMsNS43Mi04LjkzLDcuNzZjLTcuMzQsNS41Ny0xNS44Nyw4LjM0LTI1LjU3LDguMzRjLTYuMTUsMC0xMS4xMy0yLjA2LTE0LjkxLTYuMjEKCQkJCWMtMy43OS00LjEzLTYuNTMtMTEuMDYtOC4xNy0yMC43OGMyNi43NC0zNi40NCw0Ny45My03My4yNiw2My41Ni0xMTAuNDRjMTUuNjMtMzcuMTYsMjMuNDQtNjkuODQsMjMuNDQtOTguMDIKCQkJCWMwLTE5LjY1LTMuMjUtMzQuNzQtOS43Ni00NS4yN2MtNi41My0xMC41My0xNS40Ni0xNS44LTI2LjgyLTE1LjhjLTIwLjEyLDAtMzcuNDYsMTMuMjUtNTIuMDMsMzkuNzYKCQkJCWMtMTQuNTUsMjYuNTEtMjUuNTcsNTguMjQtMzMuMDMsOTUuMTdjLTcuNDUsMzYuOTMtMTEuMTksNjkuODQtMTEuMTksOTguNzRjMCwxMS44OSwwLjc5LDIyLjkxLDIuMzgsMzMuMDQKCQkJCWMyLjA2LDEzLjQyLDUuNTMsMjUuMzMsMTAuMzgsMzUuNzFjMC43NCwxLjYyLDEuNTMsMy4yMSwyLjM0LDQuNzZjMTAuMDYsMTguOTUsMjUuNTEsMjguNCw0Ni4zNSwyOC40CgkJCQljMTUuMTUsMCwyOC43LTQuMDIsNDAuNjUtMTIuMDZjMy43OS0yLjU3LDcuNTEtNS4zNCwxMS4xMi04LjM2YzcuNzgtNi40NSwxNS4xNC0xMy45NywyMi4xLTIyLjU1YzQuNDktNS4xOSw2Ljc0LTEyLjUzLDYuNzQtMjIKCQkJCUMxMDY0LjExLDM4MC4zNCwxMDYzLjIzLDM3Ni40NCwxMDYxLjQ1LDM3My42MXogTTk3My45MywyNTIuNTFjNS4xOS0yOS4xMiwxMS4yMy01My41LDE4LjEtNzMuMTUKCQkJCWM2Ljg3LTE5LjY2LDEzLjAyLTI5LjQ4LDE4LjQ4LTI5LjQ4YzYuNjIsMCw5Ljk1LDksOS45NSwyNi45OWMwLDIyLjk3LTQuOTgsNDguMzUtMTQuOTEsNzYuMTcKCQkJCWMtOS45NSwyNy44Mi0yMy4zMyw1NS41OC00MC4xNCw4My4yOEM5NjUuODcsMzA5LjU1LDk2OC43MiwyODEuNjIsOTczLjkzLDI1Mi41MXoiLz4KCQkJCgkJCQk8bGluZWFyR3JhZGllbnQgaWQ9IlNWR0lEXzAwMDAwMDQ0ODY0NDU5ODE4NDk5ODM0NDgwMDAwMDE0NzUwODc5MzcyMTAyNDYzMzk3XyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIHgxPSIxMzguNTg5NCIgeTE9IjMzNC4xNDA1IiB4Mj0iMTEzOS4yMzcyIiB5Mj0iMjgxLjE4OSIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgxIDAgMCAtMSAwIDY1MCkiPgoJCQkJPHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6I0UwNEY4QSIvPgoJCQkJPHN0b3AgIG9mZnNldD0iMSIgc3R5bGU9InN0b3AtY29sb3I6I0VDOUEyQyIvPgoJCQk8L2xpbmVhckdyYWRpZW50PgoJCQk8cGF0aCBzdHlsZT0iZmlsbDp1cmwoI1NWR0lEXzAwMDAwMDQ0ODY0NDU5ODE4NDk5ODM0NDgwMDAwMDE0NzUwODc5MzcyMTAyNDYzMzk3Xyk7IiBkPSJNMTIwMi41MiwzODIuNzQKCQkJCWMtNC40Myw1Ljc2LTEwLjMsMTIuNTctMTcuMjMsMTguN2MwLDAtMTEuMTIsOS44NS0yMS4zOCw5Ljc5Yy0yLjMsMC00LjA5LTAuOTEtNC4wOS0wLjkxYy0xLjA2LTAuNTMtMi0xLjI4LTIuODMtMi4yOAoJCQkJYy0xLjc3LTIuMTMtMi42Ni00Ljk2LTIuNjYtOC41M2MwLTEwLjY0LDIuNzItMjkuNTksOC4xNy01Ni44YzQuMDYtMjAuMjcsNy40NC0zMC4xMSw1LjMyLTM1LjUyCgkJCQljLTcuMjYtMTguNTctMzcuNDUtMjcuMDctNjAuNy0yMy43N2MtMTUuNTgsMi4yMS0yNi40Myw5LjMtMzMuNTgsMTQuMzZjLTE0LjU3LDEwLjMtMjYuMjMsMjMuOTEtMzQuOTksNDAuODQKCQkJCXMtMTMuMTMsMzQuODgtMTMuMTMsNTMuOGMwLDAuOTEsMC4wMiwxLjgxLDAuMDYsMi43MmMwLjM2LDEzLjc4LDMuNjIsMjUuMzYsOS44MSwzNC43NGMxLDEuNTUsMi4wOSwzLjAyLDMuMjYsNC40NQoJCQkJYzguNzYsMTAuNjQsMjAuNDgsMTUuOTcsMzUuMTYsMTUuOTdjMTguNywwLDM0LjIxLTkuOTUsNDYuNTItMjkuODJjMy4zMiw5LjIzLDguMjMsMTYuNTEsMTQuNzQsMjEuODMKCQkJCWM2LjUxLDUuMzIsMTMuNjgsNy45OCwyMS40OSw3Ljk4YzEwLjE3LDAsMjAuNy00LjEzLDMxLjYxLTEyLjQyYzguNC02LjM4LDE2LjQyLTEzLjg5LDI0LjEtMjIuNTMKCQkJCUMxMjA1LjYyLDQwMy4xNiwxMjAzLjI4LDM5MS4yMywxMjAyLjUyLDM4Mi43NHogTTExMTEuNzEsMzgwLjdjLTIuMTMsMTAuMTktNS41NywxOC4zNC0xMC4zLDI0LjUxCgkJCQljLTQuNzQsNi4xNS05LjcsOS4yMy0xNC45MSw5LjIzYy01LjIxLDAtOS4zLTEuNzctMTIuMjUtNS4zMmMtMi45Ni0zLjU3LTQuNDUtOS00LjQ1LTE2LjM0YzAtMTMuMjcsMi40OS0yNS44LDcuNDUtMzcuNjUKCQkJCWM0Ljk4LTExLjgzLDExLjY2LTIxLjM2LDIwLjA4LTI4LjU5YzguNC03LjIxLDE3LjU3LTEwLjk1LDI3LjUxLTExLjE3TDExMTEuNzEsMzgwLjd6Ii8+CgkJCQoJCQkJPGxpbmVhckdyYWRpZW50IGlkPSJTVkdJRF8wMDAwMDAxMzg4NDE0OTU1MTMwMDcxMDUxMDAwMDAwOTQ1NjEzMzk1NjE1Mjg5NDYxMl8iIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iMTMyLjA3ODgiIHkxPSIyOTkuOTE3OCIgeDI9IjExMzIuNzI2NyIgeTI9IjI0Ni45NjY0IiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDEgMCAwIC0xIDAgNjUwKSI+CgkJCQk8c3RvcCAgb2Zmc2V0PSIwIiBzdHlsZT0ic3RvcC1jb2xvcjojRTA0RjhBIi8+CgkJCQk8c3RvcCAgb2Zmc2V0PSIxIiBzdHlsZT0ic3RvcC1jb2xvcjojRUM5QTJDIi8+CgkJCTwvbGluZWFyR3JhZGllbnQ+CgkJCTxwYXRoIHN0eWxlPSJmaWxsOnVybCgjU1ZHSURfMDAwMDAwMTM4ODQxNDk1NTEzMDA3MTA1MTAwMDAwMDk0NTYxMzM5NTYxNTI4OTQ2MTJfKTsiIGQ9Ik01NDkuMjksMzgyLjc0CgkJCQljLTQuNDMsNS43Ni0xMC4zLDEyLjU3LTE3LjIzLDE4LjdjMCwwLTExLjEyLDkuODUtMjEuMzgsOS43OWMtMi4zLDAtNC4wOS0wLjkxLTQuMDktMC45MWMtMS4wNi0wLjUzLTItMS4yOC0yLjgzLTIuMjgKCQkJCWMtMS43Ny0yLjEzLTIuNjYtNC45Ni0yLjY2LTguNTNjMC0xMC42NCwyLjcyLTI5LjU5LDguMTctNTYuOGM0LjA2LTIwLjI3LDcuNDQtMzAuMTEsNS4zMi0zNS41MgoJCQkJYy03LjI2LTE4LjU3LTM3LjQ1LTI3LjA3LTYwLjctMjMuNzdjLTE1LjU4LDIuMjEtMjYuNDMsOS4zLTMzLjU4LDE0LjM2Yy0xNC41NywxMC4zLTI2LjIzLDIzLjkxLTM0Ljk5LDQwLjg0CgkJCQljLTguNzYsMTYuOTMtMTMuMTMsMzQuODgtMTMuMTMsNTMuOGMwLDAuOTEsMC4wMiwxLjgxLDAuMDYsMi43MmMwLjM2LDEzLjc4LDMuNjIsMjUuMzYsOS44MSwzNC43NGMxLDEuNTUsMi4wOSwzLjAyLDMuMjYsNC40NQoJCQkJYzguNzYsMTAuNjQsMjAuNDgsMTUuOTcsMzUuMTYsMTUuOTdjMTguNywwLDM0LjIxLTkuOTUsNDYuNTItMjkuODJjMy4zMiw5LjIzLDguMjMsMTYuNTEsMTQuNzQsMjEuODMKCQkJCWM2LjUxLDUuMzIsMTMuNjgsNy45OCwyMS40OSw3Ljk4YzEwLjE3LDAsMjAuNy00LjEzLDMxLjYxLTEyLjQyYzguNC02LjM4LDE2LjQyLTEzLjg5LDI0LjEtMjIuNTMKCQkJCUM1NTIuMzksNDAzLjE2LDU1MC4wNSwzOTEuMjMsNTQ5LjI5LDM4Mi43NHogTTQ1OC40OCwzODAuN2MtMi4xMywxMC4xOS01LjU3LDE4LjM0LTEwLjMsMjQuNTFjLTQuNzQsNi4xNS05LjcsOS4yMy0xNC45MSw5LjIzCgkJCQlzLTkuMy0xLjc3LTEyLjI1LTUuMzJjLTIuOTYtMy41Ny00LjQ1LTktNC40NS0xNi4zNGMwLTEzLjI3LDIuNDktMjUuOCw3LjQ1LTM3LjY1YzQuOTgtMTEuODMsMTEuNjYtMjEuMzYsMjAuMDgtMjguNTkKCQkJCWM4LjQtNy4yMSwxNy41Ny0xMC45NSwyNy41MS0xMS4xN0w0NTguNDgsMzgwLjd6Ii8+CgkJPC9nPgoJPC9nPgoJPGc+CgkJPHBhdGggY2xhc3M9InN0NyIgZD0iTTEyODguNTksMjMwLjcyYzMuNjQtMi45MSw3LjktNS4xLDEyLjc2LTYuNTZjNC44Ni0xLjQ2LDkuOTktMi4xOSwxNS4zMi0yLjE5YzguNTMsMCwxNS44OCwxLjE1LDIyLjA5LDMuNDUKCQkJYzYuMiwyLjMzLDExLjg0LDUuNDMsMTYuOTcsOS4zYzUuMSwzLjksOS43Nyw4LjQ2LDE0LjAzLDEzLjY4YzQuMjUsNS4yNCw4LjY5LDEwLjksMTMuMzIsMTYuOTdsMzcuMjItMzIuODMKCQkJYy03LjMxLTguNTEtMTQuNTktMTYuMDUtMjEuOS0yMi42M2MtNy4yOC02LjU2LTE1LjA5LTEyLjE1LTIzLjMzLTE2Ljc4Yy04LjI3LTQuNjEtMTcuMTEtOC4xMy0yNi40Ni0xMC41NwoJCQljLTkuMzgtMi40Mi0xOS44OC0zLjY0LTMxLjU2LTMuNjRjLTExLjkxLDAtMjMuNTksMS42OS0zNS4wNCw1LjFjLTExLjQyLDMuNDEtMjEuNjQsOC4zOS0zMC42NCwxNC45NwoJCQljLTksNi41Ni0xNi4yNCwxNC44My0yMS43MSwyNC43OWMtNS40NSw5Ljk5LTguMiwyMS41Mi04LjIsMzQuNjZjMCwxMy42MywzLjQxLDI1LjA1LDEwLjIyLDM0LjMxCgkJCWM2LjgxLDkuMjMsMTUuMzcsMTcuMDgsMjUuNzEsMjMuNTJjMTAuMzQsNi40NiwyMS41NSwxMS45MSwzMy41OCwxNi40MmMxMi4wMyw0LjQ5LDIzLjIyLDguOTMsMzMuNTUsMTMuMzIKCQkJYzEwLjM0LDQuMzcsMTguOTIsOS4wNSwyNS43MywxNC4wM2M2Ljc5LDUsMTAuMjIsMTEuMjYsMTAuMjIsMTguOGMwLDUuNTktMS40MSwxMC4zOS00LjIxLDE0LjRjLTIuOCw0LjAyLTYuMjcsNy4zNS0xMC4zOSwxMC4wMwoJCQljLTQuMTYsMi42OC04Ljc2LDQuNy0xMy44Niw2LjAyYy01LjEyLDEuMzQtMTAuMSwyLjAyLTE0Ljk3LDIuMDJjLTksMC0xNy4wOC0xLjI5LTI0LjI3LTMuODNjLTEuMzYtMC40OS0xMC41NS0zLjY5LTE5LjUtMTAuMjIKCQkJYy0xOS42OS0xNC4zOC0yNi45Ny0zNi42My0yOS4xMS00NC4xM2MtMTAuOTcsOS40LTIxLjkyLDE4LjgtMzIuOSwyOC4yYzEuMzYsOS44NSw1LjQsMjYuNjcsMTguNTksNDAuNzQKCQkJYzguMjcsOC44MSwxNy41MywxMy42LDI0LjYzLDE3LjUxYzguNjUsNC43NSwxNy45Myw4LjI3LDI3LjkyLDEwLjU3YzkuOTYsMi4zLDIxLjE1LDMuNDgsMzMuNTUsMy40OAoJCQljMTAuNzEsMCwyMS45LTEuNzIsMzMuNTgtNS4xMmMxMS42OC0zLjM4LDIyLjM3LTguMzksMzIuMS0xNC45NGM5LjczLTYuNTgsMTcuNzYtMTQuNjYsMjQuMDgtMjQuMjcKCQkJYzYuMzItOS41OSw5LjQ3LTIwLjYxLDkuNDctMzMuMDFjMC0xMy42MS0zLjQxLTI1LjA1LTEwLjItMzQuMjhjLTYuODEtOS4yNi0xNS4zOS0xNy4wNC0yNS43My0yMy4zNgoJCQljLTEwLjM0LTYuMzItMjEuNDgtMTEuNjgtMzMuMzctMTYuMDVjLTExLjk0LTQuMzctMjMuMDUtOC42OS0zMy4zOS0xMi45NWMtMTAuMzQtNC4yNS0xOC45Mi04Ljk1LTI1LjczLTE0LjA1CgkJCWMtNi44MS01LjEtMTAuMi0xMS40Mi0xMC4yLTE4Ljk2YzAtNS41OSwxLjA4LTEwLjYsMy4yNy0xNC45N0MxMjgyLjAxLDIzNy4zLDEyODQuOTUsMjMzLjY1LDEyODguNTksMjMwLjcyeiIvPgoJCTxwYXRoIGNsYXNzPSJzdDciIGQ9Ik0xNzg3LjY1LDI1NC44bC01My4yNywxMTkuM2wtNTMuNjItMTE5LjNoLTM1LjM5aC0yMC44aC00NS4yM2wtNzguMDYsNjIuMzljMCwwLTAuODItMTQ2LjU1LTEuMTUtMTU0LjE3CgkJCWMtOC43Miw3LjYxLTE3LjQxLDE1LjIzLTI2LjEzLDIyLjg0Yy04LjY3LDcuNTktMTcuMzIsMTUuMTYtMjUuOTksMjIuNzJ2MzAuNTJ2MjA3Ljk1aDUzLjI3VjM3NC4xbDEyLjM4LTEwLjIybDYzLjQ5LDgzLjE4aDYxLjI4CgkJCWwtODUuNzItMTE1LjI4bDc3LjQ3LTY0LjM2bDc1LjczLDE3MC41MmwtNDEuNTksOTQuODZoNTUuNDVsMTIzLjMxLTI3OEwxNzg3LjY1LDI1NC44TDE3ODcuNjUsMjU0Ljh6Ii8+Cgk8L2c+CjwvZz4KPC9zdmc+Cg==" alt="VanillaSky"><a class="doc-link" href="../../README.md">SDK documentation <span aria-hidden="true">↗</span></a></header>
86
+ <div class="doc-intro"><div class="doc-kicker">The immersive interface · Component reference</div><h1>The picture comes first.<br><span>Conversation stays close.</span></h1><p class="doc-lede">One video canvas. A quiet layer of controls. Every surface, state and detail of the current VanillaSky experience, together in one place.</p></div>
87
+ <nav class="doc-index" aria-label="Reference sections"><a href="#surfaces">Surfaces & navigation</a><a href="#panels">Settings & history</a><a href="#conversation">Conversation</a><a href="#captions">Subtitles</a><a href="#suggestions">Suggestions</a><a href="#foundations">Foundations</a></nav>
88
+ <section class="doc-section" id="surfaces"><div class="section-heading"><span class="number">01</span><h2>Present without competing</h2></div><p class="section-copy">Dark glass, soft edges and restrained lavender. Navigation sits above the picture, with the logo and a quiet cluster of actions.</p>
89
+ <div class="doc-preview"><header class="chrome"><div class="session-brand"><img class="brand-logo" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDI4LjEuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHZpZXdCb3g9IjE1NSAxMTMgMTY5MCA0MjIiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMTU1IDExMyAxNjkwIDQyMjsiIHhtbDpzcGFjZT0icHJlc2VydmUiPgo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPgoJLnN0MHtmaWxsOnVybCgjU1ZHSURfMV8pO30KCS5zdDF7ZmlsbDp1cmwoI1NWR0lEXzAwMDAwMDEzMTc5MjQ3NzkzMzEzNjczNjYwMDAwMDA5NTAyNDY0NTI0MDQ3MTc5Njg2Xyk7fQoJLnN0MntmaWxsOnVybCgjU1ZHSURfMDAwMDAxMTQwNzU2MTAxNzA2MjA3NDYzMDAwMDAwMTMwNzY4NTczMjc1MDMwNTk4NTJfKTt9Cgkuc3Qze2ZpbGw6dXJsKCNTVkdJRF8wMDAwMDAzOTg0Mzk1Mzc4NTIyOTI0Mjg4MDAwMDAwODQwMzMzMzkyMDEyMjcwNTMyOF8pO30KCS5zdDR7ZmlsbDp1cmwoI1NWR0lEXzAwMDAwMDI3NTkyNTEzNTc2NDg3NDgzMzAwMDAwMDE2NzQwODQ2NzM4OTM4NjE5NzkyXyk7fQoJLnN0NXtmaWxsOnVybCgjU1ZHSURfMDAwMDAwNzM2ODI1Njc2NTkxMzUzNzk0NjAwMDAwMDQyOTE4NTk2MTM4MzIzNjcyNDZfKTt9Cgkuc3Q2e2ZpbGw6dXJsKCNTVkdJRF8wMDAwMDA0MzQyOTI4Mzg1Nzk2OTQ0NDE5MDAwMDAwNzg0MjM5Nzg0MTEwMTYxNjAxN18pO30KCS5zdDd7ZmlsbDojRkZGRkZGO30KPC9zdHlsZT4KPGc+Cgk8Zz4KCQk8Zz4KCQkJCgkJCQk8bGluZWFyR3JhZGllbnQgaWQ9IlNWR0lEXzFfIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjE0NC43Mzg4IiB5MT0iMzYxLjU0MjIiIHgyPSIxMTQ1LjM4NjYiIHkyPSIzMDguNTkwNyIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgxIDAgMCAtMSAwIDY1MCkiPgoJCQkJPHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6I0UwNEY4QSIvPgoJCQkJPHN0b3AgIG9mZnNldD0iMSIgc3R5bGU9InN0b3AtY29sb3I6I0VDOUEyQyIvPgoJCQk8L2xpbmVhckdyYWRpZW50PgoJCQk8cGF0aCBjbGFzcz0ic3QwIiBkPSJNNDMxLjkzLDI5OC42N2MtMC42Mi0wLjYtMS4zNi0xLjExLTIuMTktMS41N2MtMi40Mi0xLjMyLTUuNjQtMS45OC05LjctMS45OAoJCQkJYy0xNi4xMiwwLTMwLjQ0LTEuMDYtNDIuOTctMy4xOWMxMS44My0zMi4yLDE3Ljc2LTYxLjkyLDE3Ljc2LTg5LjE1YzAtMTguOTMtNC40NS0zMy44NC0xMy4zMi00NC43NAoJCQkJYy04Ljg5LTEwLjg3LTIwLjg5LTE2LjMyLTM2LjA1LTE2LjMyYy0xMi4zMiwwLTIzLjUsMy4xOS0zMy41NSw5LjU5Yy0xMC4wOCw2LjQtMTgsMTYuMDQtMjMuOCwyOC45NQoJCQkJYy01LjgxLDEyLjg5LTguNywyOC43LTguNyw0Ny40MWMwLDE4LjcsMy42NiwzNS4yMSwxMSw0OS41NGM3LjM0LDE0LjMyLDE4LjIzLDI1Ljk5LDMyLjY3LDM0Ljk3CgkJCQljLTEyLjA2LDI1LjgyLTI1LjMzLDQ3LjI0LTM5Ljc2LDY0LjI4Yy0xNC40NiwxNy4wNi0yNy44MiwyNS41Ny00MC4xNCwyNS41N2MtMTIuMDYsMC0yMS4xMi05LjQtMjcuMTYtMjguMjMKCQkJCWMtNi4wNC0xOC44Mi05LjA2LTQ2LjMzLTkuMDYtODIuNTZjMC0zNC41NSwzLjU1LTczLjE1LDEwLjY2LTExNS43NmMwLjQ3LTMuNzksMC43LTYuNCwwLjctNy44MWMwLTEzLjUxLTcuODEtMjAuMjUtMjMuNDQtMjAuMjUKCQkJCWMtOS40NywwLTE2LjE1LDIuMTktMjAuMDYsNi41N3MtNi45MywxMi43NC05LjA2LDI1LjA0Yy01LjkzLDMzLjE0LTguODcsNzAuNTQtOC44NywxMTIuMjFjMCw0OC43OCw2LjA0LDg3LjQ5LDE4LjEsMTE2LjEyCgkJCQljMTIuMDgsMjguNjcsMzAuNDIsNDIuOTcsNTUuMDUsNDIuOTdjMjMuOTEsMCw0Ny43Ni0xMS42NCw3MS41Ni0zNC45N2MyMy44LTIzLjMzLDQ0LjA4LTUyLjYxLDYwLjktODcuODkKCQkJCWMxMC42MSwyLjQsMjIuMzMsMy43OSwzNS4xNCw0LjIxYzQuOTMsMC4xNywxMC4wMiwwLjE3LDE1LjI5LDAuMDRjNy44MS0wLjIzLDEzLjU1LTIuNzIsMTcuMjMtNy40NQoJCQkJYzMuNjYtNC43NCw1LjUxLTEwLjE3LDUuNTEtMTYuMzJDNDM1LjY3LDMwNC4xMiw0MzQuNDIsMzAxLjA0LDQzMS45MywyOTguNjd6IE0zMzcuNjUsMjc2LjY2CgkJCQljLTE0LjkxLTExLjEzLTIyLjM4LTI4LjI5LTIyLjM4LTUxLjVjMC0xMy43MiwyLjAyLTI0LjMzLDYuMDQtMzEuNzhjNC4wNC03LjQ1LDkuMjUtMTEuMTksMTUuNjMtMTEuMTkKCQkJCWM0LjQ5LDAsOC4wNiwyLjMsMTAuNjYsNi45M2MyLjYsNC42MiwzLjkxLDExLjg5LDMuOTEsMjEuODNDMzUxLjUsMjI4LjI0LDM0Ni44NywyNTAuMTUsMzM3LjY1LDI3Ni42NnoiLz4KCQkJCgkJCQk8bGluZWFyR3JhZGllbnQgaWQ9IlNWR0lEXzAwMDAwMDg5NTUyODM1Mzg3NjQwNjA5ODkwMDAwMDA0ODExOTA0NjIyNjQ2MDYyNzMyXyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIHgxPSIxMzcuMjUzNSIgeTE9IjMwOC44OTY2IiB4Mj0iMTEzNy45MDE0IiB5Mj0iMjU1Ljk0NTEiIGdyYWRpZW50VHJhbnNmb3JtPSJtYXRyaXgoMSAwIDAgLTEgMCA2NTApIj4KCQkJCTxzdG9wICBvZmZzZXQ9IjAiIHN0eWxlPSJzdG9wLWNvbG9yOiNFMDRGOEEiLz4KCQkJCTxzdG9wICBvZmZzZXQ9IjEiIHN0eWxlPSJzdG9wLWNvbG9yOiNFQzlBMkMiLz4KCQkJPC9saW5lYXJHcmFkaWVudD4KCQkJPHBhdGggc3R5bGU9ImZpbGw6dXJsKCNTVkdJRF8wMDAwMDA4OTU1MjgzNTM4NzY0MDYwOTg5MDAwMDAwNDgxMTkwNDYyMjY0NjA2MjczMl8pOyIgZD0iTTc0Ny45LDM3My42MQoJCQkJYy0xLjc3LTIuODUtNC4yMS00LjI3LTcuMjgtNC4yN2MtMy41NSwwLTYuNzQsMS42Ni05LjU5LDQuOTZjLTQuMSw0LjkxLTcuODcsOS4yNy0xMS4zMiwxMy4xM2MtNS43Nyw2LjQ1LTEwLjcsMTEuNDctMTQuNzgsMTUuMQoJCQkJYy02LjUxLDUuODEtMTIuMTMsOC43LTE2Ljg3LDguN2MtNi44NywwLTEwLjMtNC43Mi0xMC4zLTE0LjE5YzAtNi42MiwyLjI2LTIwLjI1LDYuNzYtNDAuODRjNS4yMS0yNC4xNiw3LjgxLTQwLjg0LDcuODEtNTAuMDkKCQkJCWMwLTE1LjM4LTcuNy0yMy4wOC0yMy4wOC0yMy4wOGMtNy44MSwwLTE2LjQsMi43NC0yNS43NCw4LjE3Yy05LjM2LDUuNDUtMTguODksMTQuNTctMjguNTksMjcuMzUKCQkJCWMtOS43MiwxMi43OC0xOC40OCwyOS4zNi0yNi4yOSw0OS43MWMwLjk0LTEwLjQsMi4xMy0xOS4xNywzLjU1LTI2LjI3YzEuNDMtNy4xLDMuMzItMTUuMzgsNS43LTI0Ljg1CgkJCQljMy41NS0xMy4yNyw1LjMyLTIxLjc4LDUuMzItMjUuNTdjMC0zLjMyLTAuOTYtNS41Ny0yLjg1LTYuNzZjLTEuODktMS4xNy01LjIxLTEuNzctOS45NS0xLjc3Yy04Ljc2LDAtMTUuNTcsMS42LTIwLjQyLDQuNzkKCQkJCWMtNC44NSwzLjIxLTguMzQsOC4yMy0xMC40NywxNS4xYy04LjM0LDI2LjM4LTEyLjcsNTQuMTYtMTMuMSw4My4zNGMtMC4wMiwxLjQ1LTAuMDQsMi45MS0wLjA0LDQuMzhjMCwxNiwxLjA4LDI4LjY3LDMuMjYsMzcuOTcKCQkJCWMwLjY0LDIuNzksMS40LDUuMywyLjI1LDcuNDljMy42Niw5LjQ3LDkuOTgsMTQuMTksMTguOTgsMTQuMTljNy4zNCwwLDEyLjc0LTEuOTQsMTYuMTctNS44NWMzLjQyLTMuOTEsNi40NC0xMS40Miw5LjA0LTIyLjU1CgkJCQljMy41Ny0xNC40NCw4LjIzLTI4LjE4LDE0LjA0LTQxLjJjNS43OS0xMy4wMiwxMS40Ny0yMy41LDE3LjA0LTMxLjQyYzUuNTctNy45Myw5Ljg5LTExLjkxLDEyLjk2LTExLjkxCgkJCQljMi42LDAsMy45MSwxLjkxLDMuOTEsNS42OGMwLDUuNy0xLjU1LDE1Ljk4LTQuNjIsMzAuOTFjLTMuMzIsMTcuMDQtNC45NiwyOC44Ny00Ljk2LDM1LjVjMCwxMy4yNywzLjA4LDIzLjM4LDkuMjMsMzAuMzYKCQkJCWM2LjE1LDYuOTgsMTUuMjcsMTAuNDcsMjcuMzUsMTAuNDdjMTQuOTEsMCwyOC4yMy00LjAyLDM5Ljk1LTEyLjA2YzUuMTctMy41NywxMC4xOS03LjU1LDE1LjA4LTExLjk2CgkJCQljNi4xNS01LjYyLDEyLjA4LTExLjkzLDE3Ljc4LTE4Ljk1YzQuNDktNS4xOSw2Ljc0LTEyLjUzLDYuNzQtMjJDNzUwLjU2LDM4MC4zNCw3NDkuNjcsMzc2LjQ0LDc0Ny45LDM3My42MXoiLz4KCQkJCgkJCQk8bGluZWFyR3JhZGllbnQgaWQ9IlNWR0lEXzAwMDAwMDM2OTY2Mjg4NDUyMDI4MTAzOTgwMDAwMDA2MTQ5NTUyMTE1MTU0NzIxOTQ4XyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIHgxPSIxMzkuNzQyOCIgeTE9IjM1NS45MzgyIiB4Mj0iMTE0MC4zOTA3IiB5Mj0iMzAyLjk4NjciIGdyYWRpZW50VHJhbnNmb3JtPSJtYXRyaXgoMSAwIDAgLTEgMCA2NTApIj4KCQkJCTxzdG9wICBvZmZzZXQ9IjAiIHN0eWxlPSJzdG9wLWNvbG9yOiNFMDRGOEEiLz4KCQkJCTxzdG9wICBvZmZzZXQ9IjEiIHN0eWxlPSJzdG9wLWNvbG9yOiNFQzlBMkMiLz4KCQkJPC9saW5lYXJHcmFkaWVudD4KCQkJPHBhdGggc3R5bGU9ImZpbGw6dXJsKCNTVkdJRF8wMDAwMDAzNjk2NjI4ODQ1MjAyODEwMzk4MDAwMDAwNjE0OTU1MjExNTE1NDcyMTk0OF8pOyIgZD0iTTgzMy40OCwzNzMuNjEKCQkJCWMtMS43Ny0yLjg1LTQuMjEtNC4yNy03LjI4LTQuMjdjLTMuNTUsMC02Ljc2LDEuNjYtOS41OSw0Ljk2Yy0yLjEzLDIuNTctNC4xNyw0Ljk4LTYuMTMsNy4yN2MtNy44NSw5LjEzLTE0LjMyLDE2LjA4LTE5LjQ0LDIwLjgKCQkJCWMtNi40LDUuOTMtMTEuNzIsOC44Ny0xNS45OCw4Ljg3Yy00LjQ5LDAtNy43LTEuODktOS41OS01LjY4Yy0xLjg5LTMuNzctMi44My05LjIzLTIuODMtMTYuMzJjMC05LjI1LDIuODMtMjYuODcsOC41MS01Mi45MgoJCQkJYzQuNDktMjEuNTMsNi43Ni0zNS4yNyw2Ljc2LTQxLjJjMC04LjA0LTYuMDQtMTIuMDgtMTguMTItMTIuMDhjLTcuODEsMC0xMy40OSwxLjQzLTE3LjA0LDQuMjdjLTMuNTUsMi44NS02LjQsOC4wNi04LjUzLDE1LjYzCgkJCQljLTQuMjcsMTQuNDQtNy43NiwzMC4wMS0xMC40Nyw0Ni43MWMtMi40NSwxNS4wNi0zLjc5LDI3LjY1LTQuMDQsMzcuOGMtMC4wMiwxLjA5LTAuMDQsMi4xNy0wLjA0LDMuMjEKCQkJCWMwLDE0LjA0LDIuMTMsMjUuOTEsNi4zOCwzNS42M2MxLjE5LDIuNzQsMi41Nyw1LjMsNC4xLDcuN2M2Ljk4LDEwLjg5LDE4LjE1LDE2LjMyLDMzLjU1LDE2LjMyYzE3Ljg3LDAsMzYuOTEtMTEuMDIsNTcuMTYtMzMuMQoJCQkJYzIuODEtMy4wOCw1LjY2LTYuMzYsOC41My05Ljg3YzQuNTEtNS4xOSw2Ljc2LTEyLjUzLDYuNzYtMjJDODM2LjE0LDM4MC4zNCw4MzUuMjYsMzc2LjQ0LDgzMy40OCwzNzMuNjF6IE03OTIuMTIsMjEwLjYxCgkJCQljLTUuNDUtNC4yNy0xMi41Ny02LjQtMjEuMzItNi40Yy05LjcsMC0xNy44MiwyLjc3LTI0LjMzLDguMzRjLTYuNTEsNS41Ny05Ljc2LDEyLjQ5LTkuNzYsMjAuNzhjMCw4LjI4LDIuNDksMTQuNzQsNy40NSwxOS4zNAoJCQkJYzQuOTgsNC42MiwxMi40NCw2LjkzLDIyLjM4LDYuOTNjMTAuMTcsMCwxOC4zNC0yLjc3LDI0LjUtOC4zNGM2LjE1LTUuNTUsOS4yMy0xMy4wOCw5LjIzLTIyLjU1CgkJCQlDODAwLjI3LDIyMC45LDc5Ny41NSwyMTQuODYsNzkyLjEyLDIxMC42MXoiLz4KCQkJCgkJCQk8bGluZWFyR3JhZGllbnQgaWQ9IlNWR0lEXzAwMDAwMTY5NTQ0MDU3OTMxOTgyMTQwNjIwMDAwMDAzNjMwOTA4MjUzMDQ2NjA0NDcxXyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIHgxPSIxNDIuNDM4MiIgeTE9IjQwNi44NzQ3IiB4Mj0iMTE0My4wODYxIiB5Mj0iMzUzLjkyMzIiIGdyYWRpZW50VHJhbnNmb3JtPSJtYXRyaXgoMSAwIDAgLTEgMCA2NTApIj4KCQkJCTxzdG9wICBvZmZzZXQ9IjAiIHN0eWxlPSJzdG9wLWNvbG9yOiNFMDRGOEEiLz4KCQkJCTxzdG9wICBvZmZzZXQ9IjEiIHN0eWxlPSJzdG9wLWNvbG9yOiNFQzlBMkMiLz4KCQkJPC9saW5lYXJHcmFkaWVudD4KCQkJPHBhdGggc3R5bGU9ImZpbGw6dXJsKCNTVkdJRF8wMDAwMDE2OTU0NDA1NzkzMTk4MjE0MDYyMDAwMDAwMzYzMDkwODI1MzA0NjYwNDQ3MV8pOyIgZD0iTTk0Ny40NywzNzMuNjEKCQkJCWMtMS43Ny0yLjg1LTQuMjEtNC4yNy03LjI4LTQuMjdjLTMuNTUsMC02Ljc0LDEuNjYtOS41OSw0Ljk2Yy0yLjExLDIuNTMtNC4xNyw0LjkxLTYuMTUsNy4xMwoJCQkJYy04LjYyLDkuNzktMTUuOTMsMTYuOTUtMjEuODksMjEuNDZjLTcuMzQsNS41Ny0xNS44Nyw4LjM0LTI1LjU3LDguMzRjLTYuMTcsMC0xMS4xMy0yLjA2LTE0LjkzLTYuMjEKCQkJCWMtMy43OS00LjEzLTYuNTEtMTEuMDYtOC4xNy0yMC43OGMyNi43Ni0zNi40NCw0Ny45NS03My4yNiw2My41OC0xMTAuNDRjMTUuNjMtMzcuMTYsMjMuNDQtNjkuODQsMjMuNDQtOTguMDIKCQkJCWMwLTE5LjY1LTMuMjYtMzQuNzQtOS43OC00NS4yN2MtNi41MS0xMC41My0xNS40NC0xNS44LTI2LjgtMTUuOGMtMjAuMTQsMC0zNy40OCwxMy4yNS01Mi4wMywzOS43NgoJCQkJYy0xNC41NywyNi41MS0yNS41Nyw1OC4yNC0zMy4wMyw5NS4xN2MtNy40NSwzNi45My0xMS4xOSw2OS44NC0xMS4xOSw5OC43NGMwLDExLjk1LDAuNzksMjMsMi40LDMzLjE4CgkJCQljMi4wNiwxMy40LDUuNTMsMjUuMjcsMTAuMzgsMzUuNjNjMC43NCwxLjYsMS41MSwzLjE3LDIuMzIsNC43YzEwLjA2LDE4Ljk1LDI1LjUsMjguNCw0Ni4zNSwyOC40CgkJCQljMTUuMTQsMCwyOC42OS00LjAyLDQwLjY1LTEyLjA2YzguNjgtNS44NSwxNi44OS0xMi44NywyNC42NS0yMS4xYzIuOTEtMy4wOSw1Ljc3LTYuMzgsOC41Ny05LjgxYzQuNDktNS4xOSw2Ljc0LTEyLjUzLDYuNzQtMjIKCQkJCUM5NTAuMTMsMzgwLjM0LDk0OS4yNCwzNzYuNDQsOTQ3LjQ3LDM3My42MXogTTg1OS45MiwyNTIuNTFjNS4yMS0yOS4xMiwxMS4yNS01My41LDE4LjEyLTczLjE1CgkJCQljNi44Ny0xOS42NiwxMy4wMi0yOS40OCwxOC40OC0yOS40OGM2LjYyLDAsOS45NSw5LDkuOTUsMjYuOTljMCwyMi45Ny00Ljk4LDQ4LjM1LTE0LjkzLDc2LjE3cy0yMy4zMyw1NS41OC00MC4xMiw4My4yOAoJCQkJQzg1MS44OCwzMDkuNTUsODU0LjcxLDI4MS42Miw4NTkuOTIsMjUyLjUxeiIvPgoJCQkKCQkJCTxsaW5lYXJHcmFkaWVudCBpZD0iU1ZHSURfMDAwMDAwOTYwMzk0OTc1NDgzNzkyMzk0NjAwMDAwMTc2ODAwODc0NTg3MzgyMjU1NjVfIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjE0Mi43NTY1IiB5MT0iNDEyLjg4ODMiIHgyPSIxMTQzLjQwNDMiIHkyPSIzNTkuOTM2OCIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgxIDAgMCAtMSAwIDY1MCkiPgoJCQkJPHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6I0UwNEY4QSIvPgoJCQkJPHN0b3AgIG9mZnNldD0iMSIgc3R5bGU9InN0b3AtY29sb3I6I0VDOUEyQyIvPgoJCQk8L2xpbmVhckdyYWRpZW50PgoJCQk8cGF0aCBzdHlsZT0iZmlsbDp1cmwoI1NWR0lEXzAwMDAwMDk2MDM5NDk3NTQ4Mzc5MjM5NDYwMDAwMDE3NjgwMDg3NDU4NzM4MjI1NTY1Xyk7IiBkPSJNMTA2MS40NSwzNzMuNjEKCQkJCWMtMS43Ny0yLjg1LTQuMjEtNC4yNy03LjI3LTQuMjdjLTMuNTcsMC02Ljc2LDEuNjYtOS42MSw0Ljk2Yy03LjE3LDguNTMtMTMuNTUsMTUuNDctMTkuMTIsMjAuODMKCQkJCWMtMy4yNSwzLjEzLTYuMjMsNS43Mi04LjkzLDcuNzZjLTcuMzQsNS41Ny0xNS44Nyw4LjM0LTI1LjU3LDguMzRjLTYuMTUsMC0xMS4xMy0yLjA2LTE0LjkxLTYuMjEKCQkJCWMtMy43OS00LjEzLTYuNTMtMTEuMDYtOC4xNy0yMC43OGMyNi43NC0zNi40NCw0Ny45My03My4yNiw2My41Ni0xMTAuNDRjMTUuNjMtMzcuMTYsMjMuNDQtNjkuODQsMjMuNDQtOTguMDIKCQkJCWMwLTE5LjY1LTMuMjUtMzQuNzQtOS43Ni00NS4yN2MtNi41My0xMC41My0xNS40Ni0xNS44LTI2LjgyLTE1LjhjLTIwLjEyLDAtMzcuNDYsMTMuMjUtNTIuMDMsMzkuNzYKCQkJCWMtMTQuNTUsMjYuNTEtMjUuNTcsNTguMjQtMzMuMDMsOTUuMTdjLTcuNDUsMzYuOTMtMTEuMTksNjkuODQtMTEuMTksOTguNzRjMCwxMS44OSwwLjc5LDIyLjkxLDIuMzgsMzMuMDQKCQkJCWMyLjA2LDEzLjQyLDUuNTMsMjUuMzMsMTAuMzgsMzUuNzFjMC43NCwxLjYyLDEuNTMsMy4yMSwyLjM0LDQuNzZjMTAuMDYsMTguOTUsMjUuNTEsMjguNCw0Ni4zNSwyOC40CgkJCQljMTUuMTUsMCwyOC43LTQuMDIsNDAuNjUtMTIuMDZjMy43OS0yLjU3LDcuNTEtNS4zNCwxMS4xMi04LjM2YzcuNzgtNi40NSwxNS4xNC0xMy45NywyMi4xLTIyLjU1YzQuNDktNS4xOSw2Ljc0LTEyLjUzLDYuNzQtMjIKCQkJCUMxMDY0LjExLDM4MC4zNCwxMDYzLjIzLDM3Ni40NCwxMDYxLjQ1LDM3My42MXogTTk3My45MywyNTIuNTFjNS4xOS0yOS4xMiwxMS4yMy01My41LDE4LjEtNzMuMTUKCQkJCWM2Ljg3LTE5LjY2LDEzLjAyLTI5LjQ4LDE4LjQ4LTI5LjQ4YzYuNjIsMCw5Ljk1LDksOS45NSwyNi45OWMwLDIyLjk3LTQuOTgsNDguMzUtMTQuOTEsNzYuMTcKCQkJCWMtOS45NSwyNy44Mi0yMy4zMyw1NS41OC00MC4xNCw4My4yOEM5NjUuODcsMzA5LjU1LDk2OC43MiwyODEuNjIsOTczLjkzLDI1Mi41MXoiLz4KCQkJCgkJCQk8bGluZWFyR3JhZGllbnQgaWQ9IlNWR0lEXzAwMDAwMDQ0ODY0NDU5ODE4NDk5ODM0NDgwMDAwMDE0NzUwODc5MzcyMTAyNDYzMzk3XyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIHgxPSIxMzguNTg5NCIgeTE9IjMzNC4xNDA1IiB4Mj0iMTEzOS4yMzcyIiB5Mj0iMjgxLjE4OSIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgxIDAgMCAtMSAwIDY1MCkiPgoJCQkJPHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6I0UwNEY4QSIvPgoJCQkJPHN0b3AgIG9mZnNldD0iMSIgc3R5bGU9InN0b3AtY29sb3I6I0VDOUEyQyIvPgoJCQk8L2xpbmVhckdyYWRpZW50PgoJCQk8cGF0aCBzdHlsZT0iZmlsbDp1cmwoI1NWR0lEXzAwMDAwMDQ0ODY0NDU5ODE4NDk5ODM0NDgwMDAwMDE0NzUwODc5MzcyMTAyNDYzMzk3Xyk7IiBkPSJNMTIwMi41MiwzODIuNzQKCQkJCWMtNC40Myw1Ljc2LTEwLjMsMTIuNTctMTcuMjMsMTguN2MwLDAtMTEuMTIsOS44NS0yMS4zOCw5Ljc5Yy0yLjMsMC00LjA5LTAuOTEtNC4wOS0wLjkxYy0xLjA2LTAuNTMtMi0xLjI4LTIuODMtMi4yOAoJCQkJYy0xLjc3LTIuMTMtMi42Ni00Ljk2LTIuNjYtOC41M2MwLTEwLjY0LDIuNzItMjkuNTksOC4xNy01Ni44YzQuMDYtMjAuMjcsNy40NC0zMC4xMSw1LjMyLTM1LjUyCgkJCQljLTcuMjYtMTguNTctMzcuNDUtMjcuMDctNjAuNy0yMy43N2MtMTUuNTgsMi4yMS0yNi40Myw5LjMtMzMuNTgsMTQuMzZjLTE0LjU3LDEwLjMtMjYuMjMsMjMuOTEtMzQuOTksNDAuODQKCQkJCXMtMTMuMTMsMzQuODgtMTMuMTMsNTMuOGMwLDAuOTEsMC4wMiwxLjgxLDAuMDYsMi43MmMwLjM2LDEzLjc4LDMuNjIsMjUuMzYsOS44MSwzNC43NGMxLDEuNTUsMi4wOSwzLjAyLDMuMjYsNC40NQoJCQkJYzguNzYsMTAuNjQsMjAuNDgsMTUuOTcsMzUuMTYsMTUuOTdjMTguNywwLDM0LjIxLTkuOTUsNDYuNTItMjkuODJjMy4zMiw5LjIzLDguMjMsMTYuNTEsMTQuNzQsMjEuODMKCQkJCWM2LjUxLDUuMzIsMTMuNjgsNy45OCwyMS40OSw3Ljk4YzEwLjE3LDAsMjAuNy00LjEzLDMxLjYxLTEyLjQyYzguNC02LjM4LDE2LjQyLTEzLjg5LDI0LjEtMjIuNTMKCQkJCUMxMjA1LjYyLDQwMy4xNiwxMjAzLjI4LDM5MS4yMywxMjAyLjUyLDM4Mi43NHogTTExMTEuNzEsMzgwLjdjLTIuMTMsMTAuMTktNS41NywxOC4zNC0xMC4zLDI0LjUxCgkJCQljLTQuNzQsNi4xNS05LjcsOS4yMy0xNC45MSw5LjIzYy01LjIxLDAtOS4zLTEuNzctMTIuMjUtNS4zMmMtMi45Ni0zLjU3LTQuNDUtOS00LjQ1LTE2LjM0YzAtMTMuMjcsMi40OS0yNS44LDcuNDUtMzcuNjUKCQkJCWM0Ljk4LTExLjgzLDExLjY2LTIxLjM2LDIwLjA4LTI4LjU5YzguNC03LjIxLDE3LjU3LTEwLjk1LDI3LjUxLTExLjE3TDExMTEuNzEsMzgwLjd6Ii8+CgkJCQoJCQkJPGxpbmVhckdyYWRpZW50IGlkPSJTVkdJRF8wMDAwMDAxMzg4NDE0OTU1MTMwMDcxMDUxMDAwMDAwOTQ1NjEzMzk1NjE1Mjg5NDYxMl8iIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iMTMyLjA3ODgiIHkxPSIyOTkuOTE3OCIgeDI9IjExMzIuNzI2NyIgeTI9IjI0Ni45NjY0IiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDEgMCAwIC0xIDAgNjUwKSI+CgkJCQk8c3RvcCAgb2Zmc2V0PSIwIiBzdHlsZT0ic3RvcC1jb2xvcjojRTA0RjhBIi8+CgkJCQk8c3RvcCAgb2Zmc2V0PSIxIiBzdHlsZT0ic3RvcC1jb2xvcjojRUM5QTJDIi8+CgkJCTwvbGluZWFyR3JhZGllbnQ+CgkJCTxwYXRoIHN0eWxlPSJmaWxsOnVybCgjU1ZHSURfMDAwMDAwMTM4ODQxNDk1NTEzMDA3MTA1MTAwMDAwMDk0NTYxMzM5NTYxNTI4OTQ2MTJfKTsiIGQ9Ik01NDkuMjksMzgyLjc0CgkJCQljLTQuNDMsNS43Ni0xMC4zLDEyLjU3LTE3LjIzLDE4LjdjMCwwLTExLjEyLDkuODUtMjEuMzgsOS43OWMtMi4zLDAtNC4wOS0wLjkxLTQuMDktMC45MWMtMS4wNi0wLjUzLTItMS4yOC0yLjgzLTIuMjgKCQkJCWMtMS43Ny0yLjEzLTIuNjYtNC45Ni0yLjY2LTguNTNjMC0xMC42NCwyLjcyLTI5LjU5LDguMTctNTYuOGM0LjA2LTIwLjI3LDcuNDQtMzAuMTEsNS4zMi0zNS41MgoJCQkJYy03LjI2LTE4LjU3LTM3LjQ1LTI3LjA3LTYwLjctMjMuNzdjLTE1LjU4LDIuMjEtMjYuNDMsOS4zLTMzLjU4LDE0LjM2Yy0xNC41NywxMC4zLTI2LjIzLDIzLjkxLTM0Ljk5LDQwLjg0CgkJCQljLTguNzYsMTYuOTMtMTMuMTMsMzQuODgtMTMuMTMsNTMuOGMwLDAuOTEsMC4wMiwxLjgxLDAuMDYsMi43MmMwLjM2LDEzLjc4LDMuNjIsMjUuMzYsOS44MSwzNC43NGMxLDEuNTUsMi4wOSwzLjAyLDMuMjYsNC40NQoJCQkJYzguNzYsMTAuNjQsMjAuNDgsMTUuOTcsMzUuMTYsMTUuOTdjMTguNywwLDM0LjIxLTkuOTUsNDYuNTItMjkuODJjMy4zMiw5LjIzLDguMjMsMTYuNTEsMTQuNzQsMjEuODMKCQkJCWM2LjUxLDUuMzIsMTMuNjgsNy45OCwyMS40OSw3Ljk4YzEwLjE3LDAsMjAuNy00LjEzLDMxLjYxLTEyLjQyYzguNC02LjM4LDE2LjQyLTEzLjg5LDI0LjEtMjIuNTMKCQkJCUM1NTIuMzksNDAzLjE2LDU1MC4wNSwzOTEuMjMsNTQ5LjI5LDM4Mi43NHogTTQ1OC40OCwzODAuN2MtMi4xMywxMC4xOS01LjU3LDE4LjM0LTEwLjMsMjQuNTFjLTQuNzQsNi4xNS05LjcsOS4yMy0xNC45MSw5LjIzCgkJCQlzLTkuMy0xLjc3LTEyLjI1LTUuMzJjLTIuOTYtMy41Ny00LjQ1LTktNC40NS0xNi4zNGMwLTEzLjI3LDIuNDktMjUuOCw3LjQ1LTM3LjY1YzQuOTgtMTEuODMsMTEuNjYtMjEuMzYsMjAuMDgtMjguNTkKCQkJCWM4LjQtNy4yMSwxNy41Ny0xMC45NSwyNy41MS0xMS4xN0w0NTguNDgsMzgwLjd6Ii8+CgkJPC9nPgoJPC9nPgoJPGc+CgkJPHBhdGggY2xhc3M9InN0NyIgZD0iTTEyODguNTksMjMwLjcyYzMuNjQtMi45MSw3LjktNS4xLDEyLjc2LTYuNTZjNC44Ni0xLjQ2LDkuOTktMi4xOSwxNS4zMi0yLjE5YzguNTMsMCwxNS44OCwxLjE1LDIyLjA5LDMuNDUKCQkJYzYuMiwyLjMzLDExLjg0LDUuNDMsMTYuOTcsOS4zYzUuMSwzLjksOS43Nyw4LjQ2LDE0LjAzLDEzLjY4YzQuMjUsNS4yNCw4LjY5LDEwLjksMTMuMzIsMTYuOTdsMzcuMjItMzIuODMKCQkJYy03LjMxLTguNTEtMTQuNTktMTYuMDUtMjEuOS0yMi42M2MtNy4yOC02LjU2LTE1LjA5LTEyLjE1LTIzLjMzLTE2Ljc4Yy04LjI3LTQuNjEtMTcuMTEtOC4xMy0yNi40Ni0xMC41NwoJCQljLTkuMzgtMi40Mi0xOS44OC0zLjY0LTMxLjU2LTMuNjRjLTExLjkxLDAtMjMuNTksMS42OS0zNS4wNCw1LjFjLTExLjQyLDMuNDEtMjEuNjQsOC4zOS0zMC42NCwxNC45NwoJCQljLTksNi41Ni0xNi4yNCwxNC44My0yMS43MSwyNC43OWMtNS40NSw5Ljk5LTguMiwyMS41Mi04LjIsMzQuNjZjMCwxMy42MywzLjQxLDI1LjA1LDEwLjIyLDM0LjMxCgkJCWM2LjgxLDkuMjMsMTUuMzcsMTcuMDgsMjUuNzEsMjMuNTJjMTAuMzQsNi40NiwyMS41NSwxMS45MSwzMy41OCwxNi40MmMxMi4wMyw0LjQ5LDIzLjIyLDguOTMsMzMuNTUsMTMuMzIKCQkJYzEwLjM0LDQuMzcsMTguOTIsOS4wNSwyNS43MywxNC4wM2M2Ljc5LDUsMTAuMjIsMTEuMjYsMTAuMjIsMTguOGMwLDUuNTktMS40MSwxMC4zOS00LjIxLDE0LjRjLTIuOCw0LjAyLTYuMjcsNy4zNS0xMC4zOSwxMC4wMwoJCQljLTQuMTYsMi42OC04Ljc2LDQuNy0xMy44Niw2LjAyYy01LjEyLDEuMzQtMTAuMSwyLjAyLTE0Ljk3LDIuMDJjLTksMC0xNy4wOC0xLjI5LTI0LjI3LTMuODNjLTEuMzYtMC40OS0xMC41NS0zLjY5LTE5LjUtMTAuMjIKCQkJYy0xOS42OS0xNC4zOC0yNi45Ny0zNi42My0yOS4xMS00NC4xM2MtMTAuOTcsOS40LTIxLjkyLDE4LjgtMzIuOSwyOC4yYzEuMzYsOS44NSw1LjQsMjYuNjcsMTguNTksNDAuNzQKCQkJYzguMjcsOC44MSwxNy41MywxMy42LDI0LjYzLDE3LjUxYzguNjUsNC43NSwxNy45Myw4LjI3LDI3LjkyLDEwLjU3YzkuOTYsMi4zLDIxLjE1LDMuNDgsMzMuNTUsMy40OAoJCQljMTAuNzEsMCwyMS45LTEuNzIsMzMuNTgtNS4xMmMxMS42OC0zLjM4LDIyLjM3LTguMzksMzIuMS0xNC45NGM5LjczLTYuNTgsMTcuNzYtMTQuNjYsMjQuMDgtMjQuMjcKCQkJYzYuMzItOS41OSw5LjQ3LTIwLjYxLDkuNDctMzMuMDFjMC0xMy42MS0zLjQxLTI1LjA1LTEwLjItMzQuMjhjLTYuODEtOS4yNi0xNS4zOS0xNy4wNC0yNS43My0yMy4zNgoJCQljLTEwLjM0LTYuMzItMjEuNDgtMTEuNjgtMzMuMzctMTYuMDVjLTExLjk0LTQuMzctMjMuMDUtOC42OS0zMy4zOS0xMi45NWMtMTAuMzQtNC4yNS0xOC45Mi04Ljk1LTI1LjczLTE0LjA1CgkJCWMtNi44MS01LjEtMTAuMi0xMS40Mi0xMC4yLTE4Ljk2YzAtNS41OSwxLjA4LTEwLjYsMy4yNy0xNC45N0MxMjgyLjAxLDIzNy4zLDEyODQuOTUsMjMzLjY1LDEyODguNTksMjMwLjcyeiIvPgoJCTxwYXRoIGNsYXNzPSJzdDciIGQ9Ik0xNzg3LjY1LDI1NC44bC01My4yNywxMTkuM2wtNTMuNjItMTE5LjNoLTM1LjM5aC0yMC44aC00NS4yM2wtNzguMDYsNjIuMzljMCwwLTAuODItMTQ2LjU1LTEuMTUtMTU0LjE3CgkJCWMtOC43Miw3LjYxLTE3LjQxLDE1LjIzLTI2LjEzLDIyLjg0Yy04LjY3LDcuNTktMTcuMzIsMTUuMTYtMjUuOTksMjIuNzJ2MzAuNTJ2MjA3Ljk1aDUzLjI3VjM3NC4xbDEyLjM4LTEwLjIybDYzLjQ5LDgzLjE4aDYxLjI4CgkJCWwtODUuNzItMTE1LjI4bDc3LjQ3LTY0LjM2bDc1LjczLDE3MC41MmwtNDEuNTksOTQuODZoNTUuNDVsMTIzLjMxLTI3OEwxNzg3LjY1LDI1NC44TDE3ODcuNjUsMjU0Ljh6Ii8+Cgk8L2c+CjwvZz4KPC9zdmc+Cg==" alt="VanillaSky"></div><div class="group"><button class="round" type="button" data-go="conversation" aria-label="New session"><svg data-icon="plus"></svg></button><button class="pill" type="button" data-go="history-demo"><svg data-icon="history"></svg><span class="nav-label">History</span></button></div><div class="group"><button class="round" type="button" id="voice-demo" aria-label="Turn voice off" aria-pressed="true"><svg data-icon="sound"></svg></button><button class="round" type="button" data-go="settings-demo" aria-label="Settings"><svg data-icon="settings"></svg></button></div></header></div>
90
+ <div class="surface-grid"><div class="surface" style="background:var(--vs-media-ground)"><strong>Canvas</strong><code>--vs-media-ground</code></div><div class="surface" style="background:var(--vs-media-glass)"><strong>Glass</strong><code>--vs-media-glass</code></div><div class="surface" style="background:var(--vs-media-hover)"><strong>Hover</strong><code>--vs-media-hover</code></div><div class="surface" style="background:var(--vs-media-selected)"><strong>Selected</strong><code>--vs-media-selected</code></div></div></section>
91
+ <section class="doc-section" id="panels"><div class="section-heading"><span class="number">02</span><h2>A place for the details</h2></div><p class="section-copy">Settings and history share the same glass surface. Switches describe the current experience; visuals and style apply to the next question. Try the controls below.</p><div class="doc-grid">
92
+ <div class="doc-preview popover-demo" id="settings-demo"><div class="sheet-popover settings"><header class="popover-heading"><h2>Settings</h2><button class="round" type="button" data-go="panels" aria-label="Back to section heading"><svg data-icon="close"></svg></button></header><fieldset class="playback-options"><legend>Watching</legend><label class="switch-row"><span><strong>Subtitles</strong><small>Read along with the answer</small></span><input type="checkbox" role="switch" checked id="show-captions"></label><label class="switch-row"><span><strong>Keep controls visible</strong><small>Keep the input bar on screen</small></span><input type="checkbox" role="switch"></label></fieldset><fieldset class="visual-options"><legend>Video creation</legend><label class="choice-row"><input type="radio" name="visuals" checked><span><strong>Templates only</strong><small>Animated text, diagrams and charts</small></span></label><label class="choice-row"><input type="radio" name="visuals"><span><strong>Some AI video</strong><small>Animation with one AI-generated scene</small></span></label><label class="choice-row"><input type="radio" name="visuals"><span><strong>Full AI video</strong><small>AI-generated footage · billed per clip</small></span></label></fieldset><fieldset class="style-options"><legend>Video style</legend><label><input type="radio" name="style" checked><span>Documentary</span></label><label><input type="radio" name="style"><span>Illustrated</span></label><label><input type="radio" name="style"><span>Blueprint</span></label></fieldset><p class="settings-note">Creation and style changes apply to your next question.</p></div></div>
93
+ <div class="doc-stack"><div class="doc-preview popover-demo" id="history-demo"><nav class="sheet-popover history" aria-label="Example session history"><div class="popover-heading"><h2>History</h2><button class="round" type="button" data-go="panels" aria-label="Back to section heading"><svg data-icon="close"></svg></button></div><section><h3 class="section-label">Current session</h3><button class="history-row current" type="button"><span class="index">01</span><span class="prompt">Why does the ocean look blue?<small>Now playing</small></span></button><button class="history-row" type="button"><span class="index">02</span><span class="prompt">What lives in the deepest part?</span></button></section><section><h3 class="section-label">Earlier sessions</h3><button class="history-row" type="button"><svg data-icon="history"></svg><span class="prompt">A different way to see the stars<small>3 completed answers</small></span></button></section></nav></div><p class="doc-note">Select a history row to try its selected state. In the experience, selecting an answer replays its video and clears the previous draft. History retains up to ten sessions in memory, including completed answers. The host owns durable persistence.</p></div>
94
+ </div></section>
95
+ <section class="doc-section" id="conversation"><div class="section-heading"><span class="number">03</span><h2>One field. Every follow-up.</h2></div><p class="section-copy">Speak or type directly over the picture. Beginning a question pauses playback. Sending starts the next answer; canceling returns to the previous playback state.</p><div class="doc-preview"><div class="demo-toolbar" aria-label="Composer preview states"><button type="button" data-state="ready" aria-pressed="true">Ready</button><button type="button" data-state="listening" aria-pressed="false">Listening</button><button type="button" data-state="thinking" aria-pressed="false">Transcribing</button></div><div class="conversation-composer"><div class="composer-meta"><span id="composer-status" role="status">Interactive preview · no microphone or model call</span></div><form class="composer" id="composer-demo"><button class="ghost transport" type="button" aria-label="Play preview" id="play-demo"><svg data-icon="play"></svg></button><label class="sr-only" for="demo-question">Question</label><textarea id="demo-question" rows="1" placeholder="Ask a follow-up…"></textarea><button class="ghost" type="button" id="mic-demo" aria-label="Preview listening state" aria-pressed="false"><svg data-icon="mic"></svg></button><button class="send" type="submit" aria-label="Preview send" disabled><svg data-icon="send"></svg></button></form></div></div><p class="doc-note">44px targets. 10px between microphone and send. The field grows to 120px and keeps the controls within reach.</p></section>
96
+ <section class="doc-section" id="captions"><div class="section-heading"><span class="number">04</span><h2>Words stay with the picture</h2></div><p class="section-copy">The first subtitle takes the input’s bottom baseline. The complete cue remains readable without truncation. Reveal the input to move subtitles upward; expand for the transcript or restore hidden subtitles in Settings.</p><div class="doc-preview"><div class="demo-toolbar"><button type="button" id="restore-caption">Show subtitles</button><button type="button" id="toggle-transcript">Expand transcript</button></div><div class="line-row" id="caption-demo" data-expanded="false"><div class="caption-actions"><button class="caption-action" type="button" id="expand-action" aria-label="Expand subtitles" aria-expanded="false">Expand <svg data-icon="up"></svg></button><button class="caption-action" type="button" id="hide-action" aria-label="Hide subtitles"><svg data-icon="close"></svg></button></div><p class="line" id="compact-caption">Water absorbs the warm colors of sunlight,<br>leaving more blue light to reach your eyes.</p><div class="expanded-captions" id="transcript-demo" tabindex="0" aria-label="Expanded subtitles" hidden><span class="eyebrow">Full answer</span><p>The ocean’s color begins with sunlight.</p><p>Water absorbs the warm colors of sunlight, leaving more blue light to reach your eyes.</p><p>Depth, particles and the sky change what we see. That is why a shallow lagoon and the open ocean can look so different.</p></div></div></div></section>
97
+ <section class="doc-section" id="suggestions"><div class="section-heading"><span class="number">05</span><h2>A little more curiosity</h2></div><p class="section-copy">A horizontal rail offers the next question. Hover or keyboard focus selects a card. Its outline and lift have room to breathe.</p><div class="doc-preview"><ul class="cards" aria-label="Example suggested questions"><li><button type="button" data-active><span class="card-art"></span><span class="card-wash"></span><span class="card-prompt">What is hiding in the deep ocean?</span></button></li><li><button type="button"><span class="card-art space"></span><span class="card-wash"></span><span class="card-prompt">Why do planets stay in orbit?</span></button></li><li><button type="button"><span class="card-art mind"></span><span class="card-wash"></span><span class="card-prompt">How does a memory begin?</span></button></li></ul></div><p class="doc-note">Reference artwork uses abstract color fields. The live rail uses the answer’s resolved media. Select a card here to place its question in the preview composer.</p></section>
98
+ <section class="doc-section" id="foundations"><div class="section-heading"><span class="number">06</span><h2>Small decisions, shared everywhere</h2></div><p class="section-copy">System typography, generous touch targets and a compact spacing scale. The video carries the color; the interface carries meaning.</p><div class="doc-preview"><div class="type-row"><span style="font-size:40px;letter-spacing:-.055em;line-height:1.08">An answer worth watching.</span><code>Display · responsive / 1.08</code></div><div class="type-row"><span style="font-size:22px;letter-spacing:-.02em;line-height:1.45">A clear line over a moving picture.</span><code>Subtitles · 17–22px / 1.45</code></div><div class="type-row"><span style="font-size:16px;letter-spacing:-.015em;line-height:1.625">Ask a follow-up…</span><code>Input · 16px / 26px</code></div><div class="type-row"><span style="font-size:13px;color:var(--vs-media-muted)">One answer leads to another.</span><code>Context · 13px</code></div><div class="metrics"><div class="metric"><strong>44<span style="display:inline;font-size:15px"> px</span></strong><span>Minimum primary control target</span></div><div class="metric"><strong>180<span style="display:inline;font-size:15px"> ms</span></strong><span>Navigation and opacity fade</span></div><div class="metric"><strong>280<span style="display:inline;font-size:15px"> ms</span></strong><span>Input and subtitle movement</span></div><div class="metric"><strong>2<span style="display:inline;font-size:15px"> s</span></strong><span>Idle delay after revealing controls</span></div></div></div><p class="doc-note">First subtitles hide the input immediately unless the viewer is editing, listening or using keyboard focus. Reduced motion removes movement and fades. Increased contrast strengthens the surfaces and borders. The input respects bottom safe areas. Subtitle actions fade while inactive and return on hover, touch or keyboard focus. The foreground preserves the scene ratio and readable text. Ambient opening media or a gradient fills the surrounding viewport.</p></section>
99
+ <footer class="doc-footer"><span>VanillaSky · VideoChat immersive interface</span><span>Rendered with the same tokens and component CSS as the experience.</span></footer>
100
+ </div></main>
101
+ <script>
102
+ for (const svg of document.querySelectorAll('svg[data-icon]')) { svg.setAttribute('viewBox','0 0 24 24'); svg.setAttribute('width','18'); svg.setAttribute('height','18'); svg.setAttribute('fill','none'); svg.setAttribute('stroke','currentColor'); svg.setAttribute('stroke-width','1.75'); svg.setAttribute('stroke-linecap','round'); svg.setAttribute('stroke-linejoin','round'); svg.setAttribute('aria-hidden','true'); const use=document.createElementNS('http://www.w3.org/2000/svg','use'); use.setAttribute('href','#'+svg.dataset.icon); svg.append(use); }
103
+ const byId=id=>document.getElementById(id);
104
+ for (const button of document.querySelectorAll('[data-go]')) button.addEventListener('click',()=>byId(button.dataset.go).scrollIntoView({block:'start'}));
105
+ byId('voice-demo').addEventListener('click',event=>{const b=event.currentTarget; const on=b.getAttribute('aria-pressed')!=='true'; b.setAttribute('aria-pressed',String(on)); b.setAttribute('aria-label',on?'Turn voice off':'Turn voice on'); b.style.opacity=on?'1':'.5';});
106
+ for (const row of document.querySelectorAll('.history-row')) row.addEventListener('click',()=>{document.querySelectorAll('.history-row').forEach(r=>r.classList.remove('current'));row.classList.add('current');});
107
+ let expanded=false;
108
+ function captions(show,expand=expanded) { expanded=expand; byId('caption-demo').hidden=!show; byId('caption-demo').dataset.expanded=String(expand); byId('compact-caption').hidden=expand; byId('transcript-demo').hidden=!expand; byId('show-captions').checked=show; byId('expand-action').firstChild.textContent=expand?'Collapse ':'Expand '; byId('expand-action').setAttribute('aria-expanded',String(expand)); byId('expand-action').setAttribute('aria-label',expand?'Collapse subtitles':'Expand subtitles'); byId('toggle-transcript').textContent=expand?'Collapse transcript':'Expand transcript'; }
109
+ byId('show-captions').addEventListener('change',e=>captions(e.target.checked,false)); byId('expand-action').addEventListener('click',()=>captions(true,!expanded)); byId('toggle-transcript').addEventListener('click',()=>captions(true,!expanded)); byId('hide-action').addEventListener('click',()=>captions(false,false)); byId('restore-caption').addEventListener('click',()=>captions(true));
110
+ const question=byId('demo-question'), send=document.querySelector('#composer-demo .send'); let state='ready';
111
+ function composer(next) { state=next; document.querySelectorAll('[data-state]').forEach(b=>b.setAttribute('aria-pressed',String(b.dataset.state===next))); byId('mic-demo').classList.toggle('listening',next==='listening'); byId('mic-demo').setAttribute('aria-pressed',String(next==='listening')); byId('composer-status').textContent=next==='listening'?'Listening… Tap the mic to finish, then review and send.':next==='thinking'?'Turning your words into a draft…':'Interactive preview · no microphone or model call'; question.placeholder=next==='listening'?'Listening…':'Ask a follow-up…'; send.disabled=!question.value.trim()||next==='thinking'; }
112
+ document.querySelectorAll('[data-state]').forEach(b=>b.addEventListener('click',()=>composer(b.dataset.state))); byId('mic-demo').addEventListener('click',()=>composer(state==='listening'?'ready':'listening')); question.addEventListener('input',()=>{send.disabled=!question.value.trim()||state==='thinking';question.style.height='auto';question.style.height=Math.min(question.scrollHeight,120)+'px';}); byId('composer-demo').addEventListener('submit',e=>{e.preventDefault();byId('composer-status').textContent='Preview question sent. The live experience turns it into a video.';question.value='';send.disabled=true;}); byId('play-demo').addEventListener('click',e=>{const b=e.currentTarget;const playing=b.getAttribute('aria-label')==='Play preview';b.setAttribute('aria-label',playing?'Pause preview':'Play preview');byId('composer-status').textContent=playing?'Playback preview: playing':'Playback preview: paused';});
113
+ for(const card of document.querySelectorAll('.cards button')) { const select=()=>{document.querySelectorAll('.cards button').forEach(b=>b.removeAttribute('data-active'));card.setAttribute('data-active','');};card.addEventListener('pointerenter',select);card.addEventListener('focus',select);card.addEventListener('click',()=>{question.value=card.querySelector('.card-prompt').textContent;composer('ready');byId('conversation').scrollIntoView({block:'start'});question.focus({preventScroll:true});}); }
114
+ </script>
115
+ </body></html>