@cmusei/console-forge 0.0.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.
- package/LICENSE.md +18 -0
- package/README.md +6 -0
- package/fesm2022/cmusei-console-forge.mjs +1397 -0
- package/fesm2022/cmusei-console-forge.mjs.map +1 -0
- package/index.d.ts +5 -0
- package/lib/components/console/console.component.d.ts +50 -0
- package/lib/components/console-status/console-status.component.d.ts +7 -0
- package/lib/components/console-toolbar/console-toolbar.component.d.ts +40 -0
- package/lib/components/console-toolbar-default/console-toolbar-default-button/console-toolbar-default-button.component.d.ts +9 -0
- package/lib/components/console-toolbar-default/console-toolbar-default.component.d.ts +30 -0
- package/lib/config/console-forge-config.d.ts +20 -0
- package/lib/config/provide-console-forge.d.ts +4 -0
- package/lib/directives/class-on-hover.directive.d.ts +10 -0
- package/lib/injection/window.injection-token.d.ts +2 -0
- package/lib/models/console-client-type.d.ts +1 -0
- package/lib/models/console-component-config.d.ts +24 -0
- package/lib/models/console-component-network-config.d.ts +4 -0
- package/lib/models/console-connection-options.d.ts +7 -0
- package/lib/models/console-connection-status.d.ts +1 -0
- package/lib/models/console-credentials.d.ts +4 -0
- package/lib/models/console-power-request.d.ts +1 -0
- package/lib/models/console-supported-features.d.ts +4 -0
- package/lib/models/console-toolbar-component-base.d.ts +5 -0
- package/lib/models/console-toolbar-context.d.ts +30 -0
- package/lib/models/console-toolbar-position.d.ts +1 -0
- package/lib/models/console-user-settings.d.ts +10 -0
- package/lib/models/log-level.d.ts +6 -0
- package/lib/services/browser-notifications/browser-notifications.service.d.ts +10 -0
- package/lib/services/browser-notifications/send-browser-notification.d.ts +9 -0
- package/lib/services/canvas-recorder/canvas-recorder.service.d.ts +14 -0
- package/lib/services/canvas-recorder/canvas-recording-settings.d.ts +9 -0
- package/lib/services/canvas-recorder/canvas-recording.d.ts +13 -0
- package/lib/services/canvas.service.d.ts +9 -0
- package/lib/services/clipboard/clipboard.helpers.d.ts +14 -0
- package/lib/services/clipboard/clipboard.service.d.ts +15 -0
- package/lib/services/console-clients/console-client-factory.service.d.ts +9 -0
- package/lib/services/console-clients/console-client.service.d.ts +23 -0
- package/lib/services/console-clients/vmware/vmware-console-client.service.d.ts +36 -0
- package/lib/services/console-clients/vnc-console-client/vnc-console-client.service.d.ts +33 -0
- package/lib/services/full-screen.service.d.ts +11 -0
- package/lib/services/logger.service.d.ts +9 -0
- package/lib/services/object.helpers.d.ts +4 -0
- package/lib/services/user-settings.service.d.ts +15 -0
- package/lib/services/uuid.service.d.ts +6 -0
- package/lib/shims/vmware-mks.models.d.ts +34 -0
- package/lib/shims/vmware-wmks.shim.d.ts +61 -0
- package/package.json +32 -0
- package/public-api.d.ts +17 -0
- package/vendor/vmware-wmks/css/extended-keypad.css +318 -0
- package/vendor/vmware-wmks/css/main-ui.css +180 -0
- package/vendor/vmware-wmks/css/trackpad.css +192 -0
- package/vendor/vmware-wmks/css/wmks-all.css +684 -0
- package/vendor/vmware-wmks/js/wmks.min.js +8 -0
|
@@ -0,0 +1,1397 @@
|
|
|
1
|
+
import * as i1 from '@angular/common';
|
|
2
|
+
import { DOCUMENT, CommonModule } from '@angular/common';
|
|
3
|
+
import * as i0 from '@angular/core';
|
|
4
|
+
import { input, inject, ElementRef, HostListener, Directive, output, Component, InjectionToken, Injectable, signal, effect, viewChild, ViewEncapsulation, Injector, computed, makeEnvironmentProviders } from '@angular/core';
|
|
5
|
+
import NoVncClient from '@novnc/novnc/core/rfb';
|
|
6
|
+
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
7
|
+
import { Subject, debounceTime } from 'rxjs';
|
|
8
|
+
|
|
9
|
+
// ===BEGIN LICENSE===
|
|
10
|
+
// Copyright 2025 Carnegie Mellon University. All rights reserved.
|
|
11
|
+
// Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
|
|
12
|
+
// ===END LICENSE===
|
|
13
|
+
var LogLevel;
|
|
14
|
+
(function (LogLevel) {
|
|
15
|
+
LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG";
|
|
16
|
+
LogLevel[LogLevel["INFO"] = 1] = "INFO";
|
|
17
|
+
LogLevel[LogLevel["WARNING"] = 2] = "WARNING";
|
|
18
|
+
LogLevel[LogLevel["ERROR"] = 3] = "ERROR";
|
|
19
|
+
})(LogLevel || (LogLevel = {}));
|
|
20
|
+
|
|
21
|
+
// ===BEGIN LICENSE===
|
|
22
|
+
// Copyright 2025 Carnegie Mellon University. All rights reserved.
|
|
23
|
+
// Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
|
|
24
|
+
// ===END LICENSE===
|
|
25
|
+
class ClassOnHoverDirective {
|
|
26
|
+
applyClasses = input.required();
|
|
27
|
+
directiveHost = inject(ElementRef);
|
|
28
|
+
handleMouseEnter() {
|
|
29
|
+
if (this.directiveHost?.nativeElement) {
|
|
30
|
+
this.directiveHost.nativeElement.classList.add(this.applyClasses());
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
handleMouseLeave() {
|
|
34
|
+
if (this.directiveHost?.nativeElement) {
|
|
35
|
+
this.directiveHost.nativeElement.classList.remove(this.applyClasses());
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ClassOnHoverDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
39
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.14", type: ClassOnHoverDirective, isStandalone: true, selector: "[cfClassOnHover]", inputs: { applyClasses: { classPropertyName: "applyClasses", publicName: "applyClasses", isSignal: true, isRequired: true, transformFunction: null } }, host: { listeners: { "mouseenter": "handleMouseEnter()", "mouseleave": "handleMouseLeave()" } }, ngImport: i0 });
|
|
40
|
+
}
|
|
41
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ClassOnHoverDirective, decorators: [{
|
|
42
|
+
type: Directive,
|
|
43
|
+
args: [{ selector: '[cfClassOnHover]' }]
|
|
44
|
+
}], propDecorators: { handleMouseEnter: [{
|
|
45
|
+
type: HostListener,
|
|
46
|
+
args: ["mouseenter"]
|
|
47
|
+
}], handleMouseLeave: [{
|
|
48
|
+
type: HostListener,
|
|
49
|
+
args: ["mouseleave"]
|
|
50
|
+
}] } });
|
|
51
|
+
|
|
52
|
+
// ===BEGIN LICENSE===
|
|
53
|
+
// Copyright 2025 Carnegie Mellon University. All rights reserved.
|
|
54
|
+
// Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
|
|
55
|
+
// ===END LICENSE===
|
|
56
|
+
class ConsoleToolbarDefaultButtonComponent {
|
|
57
|
+
clicked = output();
|
|
58
|
+
disabled = input(false);
|
|
59
|
+
label = input();
|
|
60
|
+
isOngoing = input(false);
|
|
61
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConsoleToolbarDefaultButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
62
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: ConsoleToolbarDefaultButtonComponent, isStandalone: true, selector: "cf-console-toolbar-default-button", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, isOngoing: { classPropertyName: "isOngoing", publicName: "isOngoing", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { clicked: "clicked" }, ngImport: i0, template: "<!-- ===BEGIN LICENSE=== -->\n<!-- Copyright 2025 Carnegie Mellon University. All rights reserved. -->\n<!-- Released under an MIT (SEI)-style license. See the LICENSE.md file for license information. -->\n<!-- ===END LICENSE=== -->\n\n<div class=\"svg-button\" cfClassOnHover applyClasses=\"hovered\" [ariaDisabled]=\"disabled()\"\n [class.cursor-pointer]=\"!disabled()\" [class.disabled]=\"disabled()\" [class.ongoing]=\"isOngoing()\"\n (click)=\"!disabled() && clicked.emit()\">\n <div class=\"svg-container\">\n <ng-content></ng-content>\n </div>\n\n @if (label()) {\n <div class=\"button-label\">{{ label() }}</div>\n }\n</div>\n", styles: [":host{background-color:transparent}@keyframes glow-button-color{0%{color:var(--pico-muted-color);fill:var(--pico-muted-color);stroke:var(--pico-muted-color)}35%{color:#ee402e;fill:#ee402e;stroke:#ee402e}65%{color:#ee402e;fill:#ee402e;stroke:#ee402e}to{color:var(--pico-muted-color);fill:var(--pico-muted-color);stroke:var(--pico-muted-color)}}.svg-button{border:none;border-width:0!important;color:var(--pico-color);display:flex;font-weight:400;align-items:center;flex-direction:column;justify-content:center;margin:0}.svg-button:hover:not(.disabled){color:var(--pico-primary);fill:var(--pico-primary);stroke:var(--pico-primary);transition:all .3s ease}.svg-button.ongoing{animation:glow-button-color 2s infinite}.svg-button.disabled{color:var(--pico-muted-color)}.svg-container{height:52px;width:52px}.button-label{font-size:.8rem;margin:0;text-align:center}.cursor-pointer{cursor:pointer}::ng-deep svg{height:100%;width:100%;padding:1rem}::ng-deep svg,::ng-deep path,::ng-deep rect{fill:var(--pico-color);stroke:var(--pico-color)}::ng-deep svg.disabled,::ng-deep path.disabled,::ng-deep rect.disabled{fill:var(--pico-muted-color);stroke:var(--pico-muted-color)}::ng-deep svg:hover,::ng-deep path:hover,::ng-deep rect:hover{color:var(--pico-color);transition:fill .3s ease}::ng-deep .hovered:not(.disabled) svg,::ng-deep .hovered:not(.disabled) path,::ng-deep .hovered:not(.disabled) rect{fill:var(--pico-primary);stroke:var(--pico-primary);transition:all .3s ease}::ng-deep .ongoing:not(.disabled) svg,::ng-deep .ongoing:not(.disabled) path,::ng-deep .ongoing:not(.disabled) rect,::ng-deep .ongoing:not(.disabled) .svg-button{animation:glow-button-color 2s infinite}\n"], dependencies: [{ kind: "directive", type: ClassOnHoverDirective, selector: "[cfClassOnHover]", inputs: ["applyClasses"] }] });
|
|
63
|
+
}
|
|
64
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConsoleToolbarDefaultButtonComponent, decorators: [{
|
|
65
|
+
type: Component,
|
|
66
|
+
args: [{ selector: 'cf-console-toolbar-default-button', imports: [ClassOnHoverDirective], template: "<!-- ===BEGIN LICENSE=== -->\n<!-- Copyright 2025 Carnegie Mellon University. All rights reserved. -->\n<!-- Released under an MIT (SEI)-style license. See the LICENSE.md file for license information. -->\n<!-- ===END LICENSE=== -->\n\n<div class=\"svg-button\" cfClassOnHover applyClasses=\"hovered\" [ariaDisabled]=\"disabled()\"\n [class.cursor-pointer]=\"!disabled()\" [class.disabled]=\"disabled()\" [class.ongoing]=\"isOngoing()\"\n (click)=\"!disabled() && clicked.emit()\">\n <div class=\"svg-container\">\n <ng-content></ng-content>\n </div>\n\n @if (label()) {\n <div class=\"button-label\">{{ label() }}</div>\n }\n</div>\n", styles: [":host{background-color:transparent}@keyframes glow-button-color{0%{color:var(--pico-muted-color);fill:var(--pico-muted-color);stroke:var(--pico-muted-color)}35%{color:#ee402e;fill:#ee402e;stroke:#ee402e}65%{color:#ee402e;fill:#ee402e;stroke:#ee402e}to{color:var(--pico-muted-color);fill:var(--pico-muted-color);stroke:var(--pico-muted-color)}}.svg-button{border:none;border-width:0!important;color:var(--pico-color);display:flex;font-weight:400;align-items:center;flex-direction:column;justify-content:center;margin:0}.svg-button:hover:not(.disabled){color:var(--pico-primary);fill:var(--pico-primary);stroke:var(--pico-primary);transition:all .3s ease}.svg-button.ongoing{animation:glow-button-color 2s infinite}.svg-button.disabled{color:var(--pico-muted-color)}.svg-container{height:52px;width:52px}.button-label{font-size:.8rem;margin:0;text-align:center}.cursor-pointer{cursor:pointer}::ng-deep svg{height:100%;width:100%;padding:1rem}::ng-deep svg,::ng-deep path,::ng-deep rect{fill:var(--pico-color);stroke:var(--pico-color)}::ng-deep svg.disabled,::ng-deep path.disabled,::ng-deep rect.disabled{fill:var(--pico-muted-color);stroke:var(--pico-muted-color)}::ng-deep svg:hover,::ng-deep path:hover,::ng-deep rect:hover{color:var(--pico-color);transition:fill .3s ease}::ng-deep .hovered:not(.disabled) svg,::ng-deep .hovered:not(.disabled) path,::ng-deep .hovered:not(.disabled) rect{fill:var(--pico-primary);stroke:var(--pico-primary);transition:all .3s ease}::ng-deep .ongoing:not(.disabled) svg,::ng-deep .ongoing:not(.disabled) path,::ng-deep .ongoing:not(.disabled) rect,::ng-deep .ongoing:not(.disabled) .svg-button{animation:glow-button-color 2s infinite}\n"] }]
|
|
67
|
+
}] });
|
|
68
|
+
|
|
69
|
+
// ===BEGIN LICENSE===
|
|
70
|
+
// Copyright 2025 Carnegie Mellon University. All rights reserved.
|
|
71
|
+
// Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
|
|
72
|
+
// ===END LICENSE===
|
|
73
|
+
const WINDOW = new InjectionToken("Global window", { factory: () => window });
|
|
74
|
+
|
|
75
|
+
function deepMerge(target, patch) {
|
|
76
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
77
|
+
const result = { ...target };
|
|
78
|
+
for (const key in patch) {
|
|
79
|
+
const patchValue = patch[key];
|
|
80
|
+
const targetValue = target[key];
|
|
81
|
+
if (patchValue &&
|
|
82
|
+
typeof patchValue === 'object' &&
|
|
83
|
+
!Array.isArray(patchValue) &&
|
|
84
|
+
typeof targetValue === 'object') {
|
|
85
|
+
result[key] = deepMerge(targetValue, patchValue);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
result[key] = patchValue;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// ===BEGIN LICENSE===
|
|
95
|
+
// Copyright 2025 Carnegie Mellon University. All rights reserved.
|
|
96
|
+
// Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
|
|
97
|
+
// ===END LICENSE===
|
|
98
|
+
class LoggerService {
|
|
99
|
+
libConfig = inject(ConsoleForgeConfig);
|
|
100
|
+
// allow `any` here to mirror standard console.log behavior
|
|
101
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
102
|
+
log(logLevel, message, ...addl) {
|
|
103
|
+
const loggingFunction = this.resolveLoggingFunction(logLevel);
|
|
104
|
+
if (logLevel >= this.libConfig.logThreshold) {
|
|
105
|
+
loggingFunction(`ConsoleForge (${LogLevel[logLevel]}): ${message}`, ...addl);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
resolveLoggingFunction(logLevel) {
|
|
109
|
+
switch (logLevel) {
|
|
110
|
+
case LogLevel.ERROR:
|
|
111
|
+
return console.error;
|
|
112
|
+
case LogLevel.WARNING:
|
|
113
|
+
return console.warn;
|
|
114
|
+
case LogLevel.INFO:
|
|
115
|
+
return console.info;
|
|
116
|
+
case LogLevel.DEBUG:
|
|
117
|
+
return console.debug;
|
|
118
|
+
default:
|
|
119
|
+
return console.log;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: LoggerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
123
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: LoggerService, providedIn: 'root' });
|
|
124
|
+
}
|
|
125
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: LoggerService, decorators: [{
|
|
126
|
+
type: Injectable,
|
|
127
|
+
args: [{ providedIn: 'root' }]
|
|
128
|
+
}] });
|
|
129
|
+
|
|
130
|
+
// ===BEGIN LICENSE===
|
|
131
|
+
// Copyright 2025 Carnegie Mellon University. All rights reserved.
|
|
132
|
+
// Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
|
|
133
|
+
// ===END LICENSE===
|
|
134
|
+
class UserSettingsService {
|
|
135
|
+
_settings = signal({
|
|
136
|
+
console: {
|
|
137
|
+
allowCopyToLocalClipboard: true,
|
|
138
|
+
preserveAspectRatioOnScale: true
|
|
139
|
+
},
|
|
140
|
+
toolbar: {
|
|
141
|
+
dockTo: "top"
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
settings = this._settings.asReadonly();
|
|
145
|
+
logger = inject(LoggerService);
|
|
146
|
+
settingsKey = "consoleForge:userSettings";
|
|
147
|
+
window = inject(WINDOW);
|
|
148
|
+
constructor() {
|
|
149
|
+
// read out of storage
|
|
150
|
+
const storedValue = this.window.localStorage.getItem(this.settingsKey);
|
|
151
|
+
if (storedValue) {
|
|
152
|
+
try {
|
|
153
|
+
const parsedValue = JSON.parse(storedValue);
|
|
154
|
+
this._settings.update(current => ({ ...current, ...parsedValue }));
|
|
155
|
+
}
|
|
156
|
+
catch (err) {
|
|
157
|
+
this.logger.log(LogLevel.WARNING, "Couldn't load settings from local storage:", err);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// when settings are written, update local storage
|
|
161
|
+
effect(() => {
|
|
162
|
+
const current = this._settings();
|
|
163
|
+
this.window.localStorage.setItem(this.settingsKey, JSON.stringify(current));
|
|
164
|
+
this.logger.log(LogLevel.DEBUG, "Settings saved to local storage.");
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
patch(patch) {
|
|
168
|
+
this._settings.update(current => deepMerge(current, patch));
|
|
169
|
+
}
|
|
170
|
+
update(update) {
|
|
171
|
+
this._settings.update(current => ({
|
|
172
|
+
...current,
|
|
173
|
+
...update
|
|
174
|
+
}));
|
|
175
|
+
}
|
|
176
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: UserSettingsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
177
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: UserSettingsService, providedIn: 'root' });
|
|
178
|
+
}
|
|
179
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: UserSettingsService, decorators: [{
|
|
180
|
+
type: Injectable,
|
|
181
|
+
args: [{ providedIn: 'root' }]
|
|
182
|
+
}], ctorParameters: () => [] });
|
|
183
|
+
|
|
184
|
+
// ===BEGIN LICENSE===
|
|
185
|
+
// Copyright 2025 Carnegie Mellon University. All rights reserved.
|
|
186
|
+
// Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
|
|
187
|
+
// ===END LICENSE===
|
|
188
|
+
class ConsoleToolbarDefaultComponent {
|
|
189
|
+
consoleContext = input.required();
|
|
190
|
+
// component state
|
|
191
|
+
isClipboardDialogOpen = false;
|
|
192
|
+
isNetworkDialogOpen = false;
|
|
193
|
+
isPowerDialogOpen = false;
|
|
194
|
+
isSettingsDialogOpen = false;
|
|
195
|
+
// services and viewkids
|
|
196
|
+
cfConfig = inject(ConsoleForgeConfig);
|
|
197
|
+
clipboardTextInput = viewChild("clipboardText");
|
|
198
|
+
userSettings = inject(UserSettingsService).settings;
|
|
199
|
+
handleChangeToolbarPosition(position) {
|
|
200
|
+
this.consoleContext().userSettings.patch({ toolbar: { dockTo: position } });
|
|
201
|
+
}
|
|
202
|
+
handleClipboardDialogOpenClose(isOpen) {
|
|
203
|
+
this.isClipboardDialogOpen = isOpen;
|
|
204
|
+
if (isOpen) {
|
|
205
|
+
// Is there a better way to ensure .focus works other than timeouting it?
|
|
206
|
+
setTimeout(() => this.clipboardTextInput()?.nativeElement?.focus(), 100);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
handleClipboardCopyLastText(text) {
|
|
210
|
+
console.log("fyi, i would totally have copied", text);
|
|
211
|
+
}
|
|
212
|
+
handleNetworkChangeRequested(networkName) {
|
|
213
|
+
if (!networkName) {
|
|
214
|
+
this.consoleContext().networks.disconnectRequested();
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
this.consoleContext().networks.connectionRequested(networkName);
|
|
218
|
+
}
|
|
219
|
+
this.isNetworkDialogOpen = false;
|
|
220
|
+
}
|
|
221
|
+
handleNetworkDialogOpenClose(isOpen) {
|
|
222
|
+
this.isNetworkDialogOpen = isOpen;
|
|
223
|
+
}
|
|
224
|
+
handleRecordToggle() {
|
|
225
|
+
if (this.consoleContext().state.activeConsoleRecording()) {
|
|
226
|
+
this.consoleContext().console.recordScreenStop();
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
this.consoleContext().console.recordScreenStart();
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
handleSendClipboardText(event, text) {
|
|
233
|
+
event.preventDefault();
|
|
234
|
+
if (text) {
|
|
235
|
+
this.consoleContext().console.sendTextToClipboard(text);
|
|
236
|
+
}
|
|
237
|
+
this.isClipboardDialogOpen = false;
|
|
238
|
+
}
|
|
239
|
+
async handleSendPowerRequest(request) {
|
|
240
|
+
await this.consoleContext().console.sendPowerRequest(request);
|
|
241
|
+
this.isPowerDialogOpen = false;
|
|
242
|
+
}
|
|
243
|
+
handleSettingsDialogOpenClose(isOpen) {
|
|
244
|
+
this.isSettingsDialogOpen = isOpen;
|
|
245
|
+
}
|
|
246
|
+
handleSettingsAllowLocalClipboardWrite(allow) {
|
|
247
|
+
this.consoleContext().userSettings.patch({ console: { allowCopyToLocalClipboard: allow } });
|
|
248
|
+
}
|
|
249
|
+
handleSettingsPreserveAspectRatioChange(preserveAspectRatioOnScale) {
|
|
250
|
+
this.consoleContext().userSettings.patch({ console: { preserveAspectRatioOnScale } });
|
|
251
|
+
}
|
|
252
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConsoleToolbarDefaultComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
253
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: ConsoleToolbarDefaultComponent, isStandalone: true, selector: "cf-console-toolbar-default", inputs: { consoleContext: { classPropertyName: "consoleContext", publicName: "consoleContext", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "clipboardTextInput", first: true, predicate: ["clipboardText"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- ===BEGIN LICENSE=== -->\n<!-- Copyright 2025 Carnegie Mellon University. All rights reserved. -->\n<!-- Released under an MIT (SEI)-style license. See the LICENSE.md file for license information. -->\n<!-- ===END LICENSE=== -->\n\n@if (consoleContext()) {\n<div class=\"toolbar-container\"\n [class.horizontal]=\"consoleContext().userSettings.settings().toolbar.dockTo == 'top' || consoleContext().userSettings.settings().toolbar.dockTo == 'bottom' \">\n <div class=\"button-container\">\n <cf-console-toolbar-default-button label=\"Settings\" (clicked)=\"handleSettingsDialogOpenClose(true)\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M12 8.25C9.92894 8.25 8.25 9.92893 8.25 12C8.25 14.0711 9.92894 15.75 12 15.75C14.0711 15.75 15.75 14.0711 15.75 12C15.75 9.92893 14.0711 8.25 12 8.25ZM9.75 12C9.75 10.7574 10.7574 9.75 12 9.75C13.2426 9.75 14.25 10.7574 14.25 12C14.25 13.2426 13.2426 14.25 12 14.25C10.7574 14.25 9.75 13.2426 9.75 12Z\"\n fill=\"#1C274C\"></path>\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M11.9747 1.25C11.5303 1.24999 11.1592 1.24999 10.8546 1.27077C10.5375 1.29241 10.238 1.33905 9.94761 1.45933C9.27379 1.73844 8.73843 2.27379 8.45932 2.94762C8.31402 3.29842 8.27467 3.66812 8.25964 4.06996C8.24756 4.39299 8.08454 4.66251 7.84395 4.80141C7.60337 4.94031 7.28845 4.94673 7.00266 4.79568C6.64714 4.60777 6.30729 4.45699 5.93083 4.40743C5.20773 4.31223 4.47642 4.50819 3.89779 4.95219C3.64843 5.14353 3.45827 5.3796 3.28099 5.6434C3.11068 5.89681 2.92517 6.21815 2.70294 6.60307L2.67769 6.64681C2.45545 7.03172 2.26993 7.35304 2.13562 7.62723C1.99581 7.91267 1.88644 8.19539 1.84541 8.50701C1.75021 9.23012 1.94617 9.96142 2.39016 10.5401C2.62128 10.8412 2.92173 11.0602 3.26217 11.2741C3.53595 11.4461 3.68788 11.7221 3.68786 12C3.68785 12.2778 3.53592 12.5538 3.26217 12.7258C2.92169 12.9397 2.62121 13.1587 2.39007 13.4599C1.94607 14.0385 1.75012 14.7698 1.84531 15.4929C1.88634 15.8045 1.99571 16.0873 2.13552 16.3727C2.26983 16.6469 2.45535 16.9682 2.67758 17.3531L2.70284 17.3969C2.92507 17.7818 3.11058 18.1031 3.28089 18.3565C3.45817 18.6203 3.64833 18.8564 3.89769 19.0477C4.47632 19.4917 5.20763 19.6877 5.93073 19.5925C6.30717 19.5429 6.647 19.3922 7.0025 19.2043C7.28833 19.0532 7.60329 19.0596 7.8439 19.1986C8.08452 19.3375 8.24756 19.607 8.25964 19.9301C8.27467 20.3319 8.31403 20.7016 8.45932 21.0524C8.73843 21.7262 9.27379 22.2616 9.94761 22.5407C10.238 22.661 10.5375 22.7076 10.8546 22.7292C11.1592 22.75 11.5303 22.75 11.9747 22.75H12.0252C12.4697 22.75 12.8407 22.75 13.1454 22.7292C13.4625 22.7076 13.762 22.661 14.0524 22.5407C14.7262 22.2616 15.2616 21.7262 15.5407 21.0524C15.686 20.7016 15.7253 20.3319 15.7403 19.93C15.7524 19.607 15.9154 19.3375 16.156 19.1985C16.3966 19.0596 16.7116 19.0532 16.9974 19.2042C17.3529 19.3921 17.6927 19.5429 18.0692 19.5924C18.7923 19.6876 19.5236 19.4917 20.1022 19.0477C20.3516 18.8563 20.5417 18.6203 20.719 18.3565C20.8893 18.1031 21.0748 17.7818 21.297 17.3969L21.3223 17.3531C21.5445 16.9682 21.7301 16.6468 21.8644 16.3726C22.0042 16.0872 22.1135 15.8045 22.1546 15.4929C22.2498 14.7697 22.0538 14.0384 21.6098 13.4598C21.3787 13.1586 21.0782 12.9397 20.7378 12.7258C20.464 12.5538 20.3121 12.2778 20.3121 11.9999C20.3121 11.7221 20.464 11.4462 20.7377 11.2742C21.0783 11.0603 21.3788 10.8414 21.6099 10.5401C22.0539 9.96149 22.2499 9.23019 22.1547 8.50708C22.1136 8.19546 22.0043 7.91274 21.8645 7.6273C21.7302 7.35313 21.5447 7.03183 21.3224 6.64695L21.2972 6.60318C21.0749 6.21825 20.8894 5.89688 20.7191 5.64347C20.5418 5.37967 20.3517 5.1436 20.1023 4.95225C19.5237 4.50826 18.7924 4.3123 18.0692 4.4075C17.6928 4.45706 17.353 4.60782 16.9975 4.79572C16.7117 4.94679 16.3967 4.94036 16.1561 4.80144C15.9155 4.66253 15.7524 4.39297 15.7403 4.06991C15.7253 3.66808 15.686 3.2984 15.5407 2.94762C15.2616 2.27379 14.7262 1.73844 14.0524 1.45933C13.762 1.33905 13.4625 1.29241 13.1454 1.27077C12.8407 1.24999 12.4697 1.24999 12.0252 1.25H11.9747ZM10.5216 2.84515C10.5988 2.81319 10.716 2.78372 10.9567 2.76729C11.2042 2.75041 11.5238 2.75 12 2.75C12.4762 2.75 12.7958 2.75041 13.0432 2.76729C13.284 2.78372 13.4012 2.81319 13.4783 2.84515C13.7846 2.97202 14.028 3.21536 14.1548 3.52165C14.1949 3.61826 14.228 3.76887 14.2414 4.12597C14.271 4.91835 14.68 5.68129 15.4061 6.10048C16.1321 6.51968 16.9974 6.4924 17.6984 6.12188C18.0143 5.9549 18.1614 5.90832 18.265 5.89467C18.5937 5.8514 18.9261 5.94047 19.1891 6.14228C19.2554 6.19312 19.3395 6.27989 19.4741 6.48016C19.6125 6.68603 19.7726 6.9626 20.0107 7.375C20.2488 7.78741 20.4083 8.06438 20.5174 8.28713C20.6235 8.50382 20.6566 8.62007 20.6675 8.70287C20.7108 9.03155 20.6217 9.36397 20.4199 9.62698C20.3562 9.70995 20.2424 9.81399 19.9397 10.0041C19.2684 10.426 18.8122 11.1616 18.8121 11.9999C18.8121 12.8383 19.2683 13.574 19.9397 13.9959C20.2423 14.186 20.3561 14.29 20.4198 14.373C20.6216 14.636 20.7107 14.9684 20.6674 15.2971C20.6565 15.3799 20.6234 15.4961 20.5173 15.7128C20.4082 15.9355 20.2487 16.2125 20.0106 16.6249C19.7725 17.0373 19.6124 17.3139 19.474 17.5198C19.3394 17.72 19.2553 17.8068 19.189 17.8576C18.926 18.0595 18.5936 18.1485 18.2649 18.1053C18.1613 18.0916 18.0142 18.045 17.6983 17.8781C16.9973 17.5075 16.132 17.4803 15.4059 17.8995C14.68 18.3187 14.271 19.0816 14.2414 19.874C14.228 20.2311 14.1949 20.3817 14.1548 20.4784C14.028 20.7846 13.7846 21.028 13.4783 21.1549C13.4012 21.1868 13.284 21.2163 13.0432 21.2327C12.7958 21.2496 12.4762 21.25 12 21.25C11.5238 21.25 11.2042 21.2496 10.9567 21.2327C10.716 21.2163 10.5988 21.1868 10.5216 21.1549C10.2154 21.028 9.97201 20.7846 9.84514 20.4784C9.80512 20.3817 9.77195 20.2311 9.75859 19.874C9.72896 19.0817 9.31997 18.3187 8.5939 17.8995C7.86784 17.4803 7.00262 17.5076 6.30158 17.8781C5.98565 18.0451 5.83863 18.0917 5.73495 18.1053C5.40626 18.1486 5.07385 18.0595 4.81084 17.8577C4.74458 17.8069 4.66045 17.7201 4.52586 17.5198C4.38751 17.314 4.22736 17.0374 3.98926 16.625C3.75115 16.2126 3.59171 15.9356 3.4826 15.7129C3.37646 15.4962 3.34338 15.3799 3.33248 15.2971C3.28921 14.9684 3.37828 14.636 3.5801 14.373C3.64376 14.2901 3.75761 14.186 4.0602 13.9959C4.73158 13.5741 5.18782 12.8384 5.18786 12.0001C5.18791 11.1616 4.73165 10.4259 4.06021 10.004C3.75769 9.81389 3.64385 9.70987 3.58019 9.62691C3.37838 9.3639 3.28931 9.03149 3.33258 8.7028C3.34348 8.62001 3.37656 8.50375 3.4827 8.28707C3.59181 8.06431 3.75125 7.78734 3.98935 7.37493C4.22746 6.96253 4.3876 6.68596 4.52596 6.48009C4.66055 6.27983 4.74468 6.19305 4.81093 6.14222C5.07395 5.9404 5.40636 5.85133 5.73504 5.8946C5.83873 5.90825 5.98576 5.95483 6.30173 6.12184C7.00273 6.49235 7.86791 6.51962 8.59394 6.10045C9.31998 5.68128 9.72896 4.91837 9.75859 4.12602C9.77195 3.76889 9.80512 3.61827 9.84514 3.52165C9.97201 3.21536 10.2154 2.97202 10.5216 2.84515Z\"\n fill=\"#1C274C\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n\n <div class=\"buttons-divider\"></div>\n\n @if(cfConfig.enableClipboard) {\n <cf-console-toolbar-default-button [disabled]=\"!consoleContext().state.isConnected()\" label=\"Clipboard\"\n (clicked)=\"handleClipboardDialogOpenClose(true)\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M8 5.00005C7.01165 5.00082 6.49359 5.01338 6.09202 5.21799C5.71569 5.40973 5.40973 5.71569 5.21799 6.09202C5 6.51984 5 7.07989 5 8.2V17.8C5 18.9201 5 19.4802 5.21799 19.908C5.40973 20.2843 5.71569 20.5903 6.09202 20.782C6.51984 21 7.07989 21 8.2 21H15.8C16.9201 21 17.4802 21 17.908 20.782C18.2843 20.5903 18.5903 20.2843 18.782 19.908C19 19.4802 19 18.9201 19 17.8V8.2C19 7.07989 19 6.51984 18.782 6.09202C18.5903 5.71569 18.2843 5.40973 17.908 5.21799C17.5064 5.01338 16.9884 5.00082 16 5.00005M8 5.00005V7H16V5.00005M8 5.00005V4.70711C8 4.25435 8.17986 3.82014 8.5 3.5C8.82014 3.17986 9.25435 3 9.70711 3H14.2929C14.7456 3 15.1799 3.17986 15.5 3.5C15.8201 3.82014 16 4.25435 16 4.70711V5.00005\"\n stroke=\"#000000\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n }\n\n <cf-console-toolbar-default-button (clicked)=\"consoleContext().console.copyScreenshot()\"\n [disabled]=\"!consoleContext().state.isConnected()\" label=\"Screenshot\">\n <svg width=\"800px\" height=\"800px\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M9.15023 3.01742C9.13605 3.03985 9.12278 3.0676 9.11298 3.09958C9.11044 3.10789 9.10778 3.11617 9.10502 3.12442L8.36963 5.31787C8.23301 5.72537 7.85129 6 7.4215 6H3C2.44772 6 2 6.44772 2 7V20C2 20.5523 2.44771 21 3 21H21C21.5523 21 22 20.5523 22 20V7C22 6.44771 21.5523 6 21 6H16.331C15.9011 6 15.5194 5.72528 15.3828 5.31769L14.6479 3.12423C14.6452 3.11605 14.6425 3.10783 14.64 3.09958C14.6302 3.0676 14.6169 3.03985 14.6027 3.01742C14.5986 3.01089 14.5946 3.00509 14.5908 3H9.16221C9.1584 3.00509 9.15437 3.01089 9.15023 3.01742ZM7.20525 2.49911C7.43535 1.76672 8.10563 1 9.06392 1H14.6891C15.6474 1 16.3177 1.76679 16.5478 2.49922L17.0506 4H21C22.6569 4 24 5.34315 24 7V20C24 21.6569 22.6569 23 21 23H3C1.34315 23 0 21.6569 0 20V7C0 5.34315 1.34315 4 3 4H6.70206L7.20525 2.49911ZM7 13C7 10.2386 9.23858 8 12 8C14.7614 8 17 10.2386 17 13C17 15.7614 14.7614 18 12 18C9.23858 18 7 15.7614 7 13ZM12 10C10.3431 10 9 11.3431 9 13C9 14.6569 10.3431 16 12 16C13.6569 16 15 14.6569 15 13C15 11.3431 13.6569 10 12 10Z\"\n fill=\"none\" />\n </svg>\n </cf-console-toolbar-default-button>\n\n @if (cfConfig.enableConsoleRecord) {\n <cf-console-toolbar-default-button (clicked)=\"handleRecordToggle()\"\n [disabled]=\"!consoleContext().state.isRecordingAvailable()\"\n [isOngoing]=\"!!consoleContext().state.activeConsoleRecording()\" label=\"Record\">\n @if (!consoleContext().state.activeConsoleRecording()) {\n <svg viewBox=\"0 0 20 20\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\" fill=\"#000000\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <title>record [#979]</title>\n <desc>Created with Sketch.</desc>\n <defs> </defs>\n <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n <g id=\"Dribbble-Light-Preview\" transform=\"translate(-100.000000, -3879.000000)\" fill=\"#000000\">\n <g id=\"icons\" transform=\"translate(56.000000, 160.000000)\">\n <path\n d=\"M56,3719 L56,3721 L62,3721 L62,3727 L64,3727 L64,3719 L56,3719 Z M58,3729.151 C58,3726.942 56.209,3725.151 54,3725.151 C51.791,3725.151 50,3726.942 50,3729.151 C50,3731.36 51.791,3733.151 54,3733.151 C56.209,3733.151 58,3731.36 58,3729.151 L58,3729.151 Z M62,3737 L56,3737 L56,3739 L64,3739 L64,3731 L62,3731 L62,3737 Z M46,3731 L44,3731 L44,3739 L52,3739 L52,3737 L46,3737 L46,3731 Z M46,3727 L44,3727 L44,3719 L52,3719 L52,3721 L46,3721 L46,3727 Z\"\n id=\"record-[#979]\"> </path>\n </g>\n </g>\n </g>\n </g>\n </svg>\n } @else {\n <svg viewBox=\"0 -0.5 21 21\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\" fill=\"#000000\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n <g id=\"Dribbble-Light-Preview\" transform=\"translate(-59.000000, -440.000000)\" fill=\"#000000\">\n <g id=\"icons\" transform=\"translate(56.000000, 160.000000)\">\n <path\n d=\"M9.3,294 L17.7,294 L17.7,286 L9.3,286 L9.3,294 Z M15.6,280 L15.6,282 L21.9,282 L21.9,288 L24,288 L24,280 L15.6,280 Z M21.9,298 L15.6,298 L15.6,300 L24,300 L24,292 L21.9,292 L21.9,298 Z M5.1,292 L3,292 L3,300 L11.4,300 L11.4,298 L5.1,298 L5.1,292 Z M5.1,288 L3,288 L3,280 L11.4,280 L11.4,282 L5.1,282 L5.1,288 Z\"\n id=\"stop-[#1470]\"> </path>\n </g>\n </g>\n </g>\n </g>\n </svg>\n }\n </cf-console-toolbar-default-button>\n }\n\n <cf-console-toolbar-default-button (clicked)=\"consoleContext().console.toggleFullscreen()\" label=\"Fullscreen\">\n @if (consoleContext().state.isFullscreenAvailable()) {\n <svg width=\"800px\" height=\"800px\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M21.7092 2.29502C21.8041 2.3904 21.8757 2.50014 21.9241 2.61722C21.9727 2.73425 21.9996 2.8625 22 2.997L22 3V9C22 9.55228 21.5523 10 21 10C20.4477 10 20 9.55228 20 9V5.41421L14.7071 10.7071C14.3166 11.0976 13.6834 11.0976 13.2929 10.7071C12.9024 10.3166 12.9024 9.68342 13.2929 9.29289L18.5858 4H15C14.4477 4 14 3.55228 14 3C14 2.44772 14.4477 2 15 2H20.9998C21.2749 2 21.5242 2.11106 21.705 2.29078L21.7092 2.29502Z\"\n fill=\"#000000\" />\n <path\n d=\"M10.7071 14.7071L5.41421 20H9C9.55228 20 10 20.4477 10 21C10 21.5523 9.55228 22 9 22H3.00069L2.997 22C2.74301 21.9992 2.48924 21.9023 2.29502 21.7092L2.29078 21.705C2.19595 21.6096 2.12432 21.4999 2.07588 21.3828C2.02699 21.2649 2 21.1356 2 21V15C2 14.4477 2.44772 14 3 14C3.55228 14 4 14.4477 4 15V18.5858L9.29289 13.2929C9.68342 12.9024 10.3166 12.9024 10.7071 13.2929C11.0976 13.6834 11.0976 14.3166 10.7071 14.7071Z\"\n fill=\"#000000\" />\n </svg>\n } @else {\n <svg width=\"800px\" height=\"800px\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M7 9C8.10457 9 9 8.10457 9 7V3C9 2.44772 8.55228 2 8 2C7.44772 2 7 2.44772 7 3V7H3C2.44772 7 2 7.44772 2 8C2 8.55228 2.44772 9 3 9H7Z\"\n fill=\"#000000\" />\n <path\n d=\"M17 9C15.8954 9 15 8.10457 15 7V3C15 2.44772 15.4477 2 16 2C16.5523 2 17 2.44772 17 3V7H21C21.5523 7 22 7.44772 22 8C22 8.55228 21.5523 9 21 9H17Z\"\n fill=\"#000000\" />\n <path\n d=\"M17 15C15.8954 15 15 15.8954 15 17V21C15 21.5523 15.4477 22 16 22C16.5523 22 17 21.5523 17 21V17H21C21.5523 17 22 16.5523 22 16C22 15.4477 21.5523 15 21 15H17Z\"\n fill=\"#000000\" />\n <path\n d=\"M9 17C9 15.8954 8.10457 15 7 15H3C2.44772 15 2 15.4477 2 16C2 16.5523 2.44772 17 3 17H7V21C7 21.5523 7.44772 22 8 22C8.55228 22 9 21.5523 9 21V17Z\"\n fill=\"#000000\" />\n </svg>\n }\n </cf-console-toolbar-default-button>\n\n @if (consoleContext().networks.config()?.available?.length && consoleContext().state.isConnected()) {\n <div class=\"buttons-divider\"></div>\n\n <cf-console-toolbar-default-button\n label=\"Networks ({{ consoleContext().networks.config()?.available?.length }})\"\n (clicked)=\"handleNetworkDialogOpenClose(true)\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M3 12H21M12 8V12M6.5 12V16M17.5 12V16M10.1 8H13.9C14.4601 8 14.7401 8 14.954 7.89101C15.1422 7.79513 15.2951 7.64215 15.391 7.45399C15.5 7.24008 15.5 6.96005 15.5 6.4V4.6C15.5 4.03995 15.5 3.75992 15.391 3.54601C15.2951 3.35785 15.1422 3.20487 14.954 3.10899C14.7401 3 14.4601 3 13.9 3H10.1C9.53995 3 9.25992 3 9.04601 3.10899C8.85785 3.20487 8.70487 3.35785 8.60899 3.54601C8.5 3.75992 8.5 4.03995 8.5 4.6V6.4C8.5 6.96005 8.5 7.24008 8.60899 7.45399C8.70487 7.64215 8.85785 7.79513 9.04601 7.89101C9.25992 8 9.53995 8 10.1 8ZM15.6 21H19.4C19.9601 21 20.2401 21 20.454 20.891C20.6422 20.7951 20.7951 20.6422 20.891 20.454C21 20.2401 21 19.9601 21 19.4V17.6C21 17.0399 21 16.7599 20.891 16.546C20.7951 16.3578 20.6422 16.2049 20.454 16.109C20.2401 16 19.9601 16 19.4 16H15.6C15.0399 16 14.7599 16 14.546 16.109C14.3578 16.2049 14.2049 16.3578 14.109 16.546C14 16.7599 14 17.0399 14 17.6V19.4C14 19.9601 14 20.2401 14.109 20.454C14.2049 20.6422 14.3578 20.7951 14.546 20.891C14.7599 21 15.0399 21 15.6 21ZM4.6 21H8.4C8.96005 21 9.24008 21 9.45399 20.891C9.64215 20.7951 9.79513 20.6422 9.89101 20.454C10 20.2401 10 19.9601 10 19.4V17.6C10 17.0399 10 16.7599 9.89101 16.546C9.79513 16.3578 9.64215 16.2049 9.45399 16.109C9.24008 16 8.96005 16 8.4 16H4.6C4.03995 16 3.75992 16 3.54601 16.109C3.35785 16.2049 3.20487 16.3578 3.10899 16.546C3 16.7599 3 17.0399 3 17.6V19.4C3 19.9601 3 20.2401 3.10899 20.454C3.20487 20.6422 3.35785 20.7951 3.54601 20.891C3.75992 21 4.03995 21 4.6 21Z\"\n stroke=\"#000000\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n }\n\n @if (consoleContext().state.isConnected()) {\n <div class=\"buttons-divider\"></div>\n\n <cf-console-toolbar-default-button label=\"Ctrl+Alt+Del\" (clicked)=\"consoleContext().console.sendCtrlAltDel()\"\n [disabled]=\"!consoleContext().state.isConnected()\">\n <svg fill=\"#000000\" version=\"1.1\" id=\"Layer_1\" xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 8 8\" enable-background=\"new 0 0 8 8\"\n xml:space=\"preserve\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <rect x=\"2.989\" width=\"2.023\" height=\"5.471\"></rect>\n <rect x=\"2.989\" y=\"6.39\" width=\"2.023\" height=\"1.61\"></rect>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n\n @if (consoleContext().console.supportedFeatures().powerManagement) {\n <cf-console-toolbar-default-button label=\"Power\" (clicked)=\"isPowerDialogOpen = true\">\n <svg width=\"800px\" height=\"800px\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M13 3C13 2.44772 12.5523 2 12 2C11.4477 2 11 2.44772 11 3V13C11 13.5523 11.4477 14 12 14C12.5523 14 13 13.5523 13 13V3Z\"\n fill=\"none\" />\n <path\n d=\"M6.2798 6.70707C6.67031 6.31653 6.67028 5.68337 6.27973 5.29286C5.88919 4.90235 5.25603 4.90238 4.86552 5.29293C3.09635 7.06226 2 9.49298 2 12.1764C2 17.6204 6.49591 22 12 22C17.5041 22 22 17.6204 22 12.1764C22 9.49298 20.9036 7.06226 19.1345 5.29293C18.744 4.90238 18.1108 4.90235 17.7203 5.29286C17.3297 5.68337 17.3297 6.31653 17.7202 6.70707C19.1338 8.12083 20 10.0503 20 12.1764C20 16.4787 16.437 20 12 20C7.56296 20 4 16.4787 4 12.1764C4 10.0503 4.86618 8.12083 6.2798 6.70707Z\"\n fill=\"none\" />\n </svg>\n </cf-console-toolbar-default-button>\n }\n }\n </div>\n</div>\n}\n\n<dialog [open]=\"isClipboardDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"handleClipboardDialogOpenClose(false)\"></button>\n <p>\n <strong>Send Text to Console Clipboard</strong>\n </p>\n </header>\n\n <div>\n <h2>Send Text to Console</h2>\n <form (submit)=\"handleSendClipboardText($event, clipboardText.value)\">\n <fieldset role=\"group\">\n <input type=\"text\" class=\"clipboard-text\" aria-label=\"Clipboard text\"\n placeholder=\"Enter text to send to the console's clipboard\" #clipboardText autofocus>\n <button type=\"submit\"\n [disabled]=\"!clipboardText.value || !consoleContext().state.isConnected\">Send</button>\n </fieldset>\n </form>\n </div>\n\n @if(!userSettings().console.allowCopyToLocalClipboard) {\n <div>\n <h2>Console Clipboard</h2>\n <form (submit)=\"handleClipboardCopyLastText(consoleLastClipboardText.value)\">\n <fieldset role=\"group\">\n <input type=\"text\" class=\"clipboard-text\" aria-label=\"Clipboard text\"\n placeholder=\"Enter text to send to the console's clipboard\" #consoleLastClipboardText autofocus>\n <button type=\"submit\" [disabled]=\"!consoleLastClipboardText.value\">Copy</button>\n </fieldset>\n </form>\n </div>\n }\n </article>\n</dialog>\n\n<dialog [open]=\"isNetworkDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"handleNetworkDialogOpenClose(false)\"></button>\n <p>\n <strong>Select Active Network</strong>\n </p>\n </header>\n\n <form>\n <fieldset role=\"group\">\n <select #availableNetworksSelect name=\"current-network\" aria-label=\"Select a network to connect to\"\n required>\n <option selected value=\"\">\n [Disconnect from network]\n </option>\n\n @for(network of consoleContext().networks.config()?.available; track network) {\n <option [value]=\"network\" [selected]=\"network === consoleContext().networks.config()?.current\">\n {{ network }}\n </option>\n }\n </select>\n\n <button type=\"button\" (click)=\"handleNetworkChangeRequested(availableNetworksSelect.value)\">\n {{ availableNetworksSelect.value ? \"Connect\" : \"Disconnect\" }}\n </button>\n </fieldset>\n </form>\n </article>\n</dialog>\n\n\n<dialog [open]=\"isPowerDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"isPowerDialogOpen = false\"></button>\n <p>\n <strong>Console Power</strong>\n </p>\n </header>\n\n <div class=\"power-buttons\">\n <button type=\"button\" (click)=\"handleSendPowerRequest('reboot')\">Request Reboot</button>\n <button type=\"button\" (click)=\"handleSendPowerRequest('shutdown')\">Request Shutdown</button>\n <hr />\n <button class=\"secondary\" type=\"button\" (click)=\"handleSendPowerRequest('rebootHard')\">\n Request Hard Reboot\n </button>\n </div>\n </article>\n</dialog>\n\n<dialog [open]=\"isSettingsDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"handleSettingsDialogOpenClose(false)\"></button>\n <p>\n <strong>Console Settings</strong>\n </p>\n </header>\n\n <div class=\"settings-form\">\n <h4>Behavior</h4>\n <fieldset>\n <label>\n <input #inputAllowLocalClipboardWrite type=\"checkbox\" name=\"allowLocalClipboardWrite\"\n [checked]=\"consoleContext().userSettings.settings().console.allowCopyToLocalClipboard\"\n (change)=\"handleSettingsAllowLocalClipboardWrite(inputAllowLocalClipboardWrite.checked)\" />\n Allow the remote machine to copy text to my local clipboard\n </label>\n <label>\n <input #inputScaleToContainerSize type=\"checkbox\" name=\"scaleToContainerSize\"\n [checked]=\"consoleContext().userSettings.settings().console.preserveAspectRatioOnScale\"\n (change)=\"handleSettingsPreserveAspectRatioChange(inputScaleToContainerSize.checked)\" />\n Preserve console aspect ratio when scaling size\n </label>\n </fieldset>\n\n <div class=\"settings-toolbar-dock\">\n <h4>Toolbar Position</h4>\n <div role=\"group\">\n <button (click)=\"handleChangeToolbarPosition('left')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'left'\">Left</button>\n <button (click)=\"handleChangeToolbarPosition('right')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'right'\">Right</button>\n <button (click)=\"handleChangeToolbarPosition('top')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'top'\">Top</button>\n <button (click)=\"handleChangeToolbarPosition('bottom')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'bottom'\">Bottom</button>\n </div>\n </div>\n </div>\n </article>\n</dialog>\n", styles: ["@charset \"UTF-8\";:root,:host{--pico-font-family-emoji: \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";--pico-font-family-sans-serif: system-ui, \"Segoe UI\", Roboto, Oxygen, Ubuntu, Cantarell, Helvetica, Arial, \"Helvetica Neue\", sans-serif, var(--pico-font-family-emoji);--pico-font-family-monospace: ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, \"Liberation Mono\", monospace, var(--pico-font-family-emoji);--pico-font-family: var(--pico-font-family-sans-serif);--pico-line-height: 1.5;--pico-font-weight: 400;--pico-font-size: 100%;--pico-text-underline-offset: .1rem;--pico-border-radius: .25rem;--pico-border-width: .0625rem;--pico-outline-width: .125rem;--pico-transition: .2s ease-in-out;--pico-spacing: 1rem;--pico-typography-spacing-vertical: 1rem;--pico-block-spacing-vertical: var(--pico-spacing);--pico-block-spacing-horizontal: var(--pico-spacing);--pico-grid-column-gap: var(--pico-spacing);--pico-grid-row-gap: var(--pico-spacing);--pico-form-element-spacing-vertical: .75rem;--pico-form-element-spacing-horizontal: 1rem;--pico-group-box-shadow: 0 0 0 rgba(0, 0, 0, 0);--pico-group-box-shadow-focus-with-button: 0 0 0 var(--pico-outline-width) var(--pico-primary-focus);--pico-group-box-shadow-focus-with-input: 0 0 0 .0625rem var(--pico-form-element-border-color);--pico-modal-overlay-backdrop-filter: blur(.375rem);--pico-nav-element-spacing-vertical: 1rem;--pico-nav-element-spacing-horizontal: .5rem;--pico-nav-link-spacing-vertical: .5rem;--pico-nav-link-spacing-horizontal: .5rem;--pico-nav-breadcrumb-divider: \">\";--pico-icon-checkbox: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E\");--pico-icon-minus: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='5' y1='12' x2='19' y2='12'%3E%3C/line%3E%3C/svg%3E\");--pico-icon-chevron: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(136, 145, 164)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E\");--pico-icon-date: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(136, 145, 164)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E\");--pico-icon-time: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(136, 145, 164)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cpolyline points='12 6 12 12 16 14'%3E%3C/polyline%3E%3C/svg%3E\");--pico-icon-search: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(136, 145, 164)' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E\");--pico-icon-close: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(136, 145, 164)' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'%3E%3C/line%3E%3Cline x1='6' y1='6' x2='18' y2='18'%3E%3C/line%3E%3C/svg%3E\");--pico-icon-loading: url(\"data:image/svg+xml,%3Csvg fill='none' height='24' width='24' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg' %3E%3Cstyle%3E g %7B animation: rotate 2s linear infinite; transform-origin: center center; %7D circle %7B stroke-dasharray: 75,100; stroke-dashoffset: -5; animation: dash 1.5s ease-in-out infinite; stroke-linecap: round; %7D @keyframes rotate %7B 0%25 %7B transform: rotate(0deg); %7D 100%25 %7B transform: rotate(360deg); %7D %7D @keyframes dash %7B 0%25 %7B stroke-dasharray: 1,100; stroke-dashoffset: 0; %7D 50%25 %7B stroke-dasharray: 44.5,100; stroke-dashoffset: -17.5; %7D 100%25 %7B stroke-dasharray: 44.5,100; stroke-dashoffset: -62; %7D %7D %3C/style%3E%3Cg%3E%3Ccircle cx='12' cy='12' r='10' fill='none' stroke='rgb(136, 145, 164)' stroke-width='4' /%3E%3C/g%3E%3C/svg%3E\")}@media (min-width: 576px){:root,:host{--pico-font-size: 106.25%}}@media (min-width: 768px){:root,:host{--pico-font-size: 112.5%}}@media (min-width: 1024px){:root,:host{--pico-font-size: 118.75%}}@media (min-width: 1280px){:root,:host{--pico-font-size: 125%}}@media (min-width: 1536px){:root,:host{--pico-font-size: 131.25%}}a,a.secondary,a.contrast{--pico-text-decoration: underline}small{--pico-font-size: .875em}h1,h2,h3,h4,h5,h6{--pico-font-weight: 700}h1{--pico-font-size: 2rem;--pico-line-height: 1.125;--pico-typography-spacing-top: 3rem}h2{--pico-font-size: 1.75rem;--pico-line-height: 1.15;--pico-typography-spacing-top: 2.625rem}h3{--pico-font-size: 1.5rem;--pico-line-height: 1.175;--pico-typography-spacing-top: 2.25rem}h4{--pico-font-size: 1.25rem;--pico-line-height: 1.2;--pico-typography-spacing-top: 1.874rem}h5{--pico-font-size: 1.125rem;--pico-line-height: 1.225;--pico-typography-spacing-top: 1.6875rem}h6{--pico-font-size: 1rem;--pico-line-height: 1.25;--pico-typography-spacing-top: 1.5rem}thead th,thead td,tfoot th,tfoot td{--pico-font-weight: 600;--pico-border-width: .1875rem}pre,code,kbd,samp{--pico-font-family: var(--pico-font-family-monospace)}kbd{--pico-font-weight: bolder}input:not([type=submit],[type=button],[type=reset],[type=checkbox],[type=radio],[type=file]),:where(select,textarea){--pico-outline-width: .0625rem}[type=search]{--pico-border-radius: 5rem}[type=checkbox],[type=radio]{--pico-border-width: .125rem}[type=checkbox][role=switch]{--pico-border-width: .1875rem}details.dropdown summary:not([role=button]){--pico-outline-width: .0625rem}nav details.dropdown summary:focus-visible{--pico-outline-width: .125rem}[role=search]{--pico-border-radius: 5rem}[role=search]:has(button.secondary:focus,[type=submit].secondary:focus,[type=button].secondary:focus,[role=button].secondary:focus),[role=group]:has(button.secondary:focus,[type=submit].secondary:focus,[type=button].secondary:focus,[role=button].secondary:focus){--pico-group-box-shadow-focus-with-button: 0 0 0 var(--pico-outline-width) var(--pico-secondary-focus)}[role=search]:has(button.contrast:focus,[type=submit].contrast:focus,[type=button].contrast:focus,[role=button].contrast:focus),[role=group]:has(button.contrast:focus,[type=submit].contrast:focus,[type=button].contrast:focus,[role=button].contrast:focus){--pico-group-box-shadow-focus-with-button: 0 0 0 var(--pico-outline-width) var(--pico-contrast-focus)}[role=search] button,[role=search] [type=submit],[role=search] [type=button],[role=search] [role=button],[role=group] button,[role=group] [type=submit],[role=group] [type=button],[role=group] [role=button]{--pico-form-element-spacing-horizontal: 2rem}details summary[role=button]:not(.outline):after{filter:brightness(0) invert(1)}[aria-busy=true]:not(input,select,textarea):is(button,[type=submit],[type=button],[type=reset],[role=button]):not(.outline):before{filter:brightness(0) invert(1)}[data-theme=light],:root:not([data-theme=dark]),:host(:not([data-theme=dark])){color-scheme:light;--pico-background-color: #fff;--pico-color: #373c44;--pico-text-selection-color: rgba(2, 154, 232, .25);--pico-muted-color: #646b79;--pico-muted-border-color: rgb(231, 234, 239.5);--pico-primary: #0172ad;--pico-primary-background: #0172ad;--pico-primary-border: var(--pico-primary-background);--pico-primary-underline: rgba(1, 114, 173, .5);--pico-primary-hover: #015887;--pico-primary-hover-background: #02659a;--pico-primary-hover-border: var(--pico-primary-hover-background);--pico-primary-hover-underline: var(--pico-primary-hover);--pico-primary-focus: rgba(2, 154, 232, .5);--pico-primary-inverse: #fff;--pico-secondary: #5d6b89;--pico-secondary-background: #525f7a;--pico-secondary-border: var(--pico-secondary-background);--pico-secondary-underline: rgba(93, 107, 137, .5);--pico-secondary-hover: #48536b;--pico-secondary-hover-background: #48536b;--pico-secondary-hover-border: var(--pico-secondary-hover-background);--pico-secondary-hover-underline: var(--pico-secondary-hover);--pico-secondary-focus: rgba(93, 107, 137, .25);--pico-secondary-inverse: #fff;--pico-contrast: #181c25;--pico-contrast-background: #181c25;--pico-contrast-border: var(--pico-contrast-background);--pico-contrast-underline: rgba(24, 28, 37, .5);--pico-contrast-hover: #000;--pico-contrast-hover-background: #000;--pico-contrast-hover-border: var(--pico-contrast-hover-background);--pico-contrast-hover-underline: var(--pico-secondary-hover);--pico-contrast-focus: rgba(93, 107, 137, .25);--pico-contrast-inverse: #fff;--pico-box-shadow: .0145rem .029rem .174rem rgba(129, 145, 181, .01698), .0335rem .067rem .402rem rgba(129, 145, 181, .024), .0625rem .125rem .75rem rgba(129, 145, 181, .03), .1125rem .225rem 1.35rem rgba(129, 145, 181, .036), .2085rem .417rem 2.502rem rgba(129, 145, 181, .04302), .5rem 1rem 6rem rgba(129, 145, 181, .06), 0 0 0 .0625rem rgba(129, 145, 181, .015);--pico-h1-color: #2d3138;--pico-h2-color: #373c44;--pico-h3-color: #424751;--pico-h4-color: #4d535e;--pico-h5-color: #5c6370;--pico-h6-color: #646b79;--pico-mark-background-color: rgb(252.5, 230.5, 191.5);--pico-mark-color: #0f1114;--pico-ins-color: rgb(28.5, 105.5, 84);--pico-del-color: rgb(136, 56.5, 53);--pico-blockquote-border-color: var(--pico-muted-border-color);--pico-blockquote-footer-color: var(--pico-muted-color);--pico-button-box-shadow: 0 0 0 rgba(0, 0, 0, 0);--pico-button-hover-box-shadow: 0 0 0 rgba(0, 0, 0, 0);--pico-table-border-color: var(--pico-muted-border-color);--pico-table-row-stripped-background-color: rgba(111, 120, 135, .0375);--pico-code-background-color: rgb(243, 244.5, 246.75);--pico-code-color: #646b79;--pico-code-kbd-background-color: var(--pico-color);--pico-code-kbd-color: var(--pico-background-color);--pico-form-element-background-color: rgb(251, 251.5, 252.25);--pico-form-element-selected-background-color: #dfe3eb;--pico-form-element-border-color: #cfd5e2;--pico-form-element-color: #23262c;--pico-form-element-placeholder-color: var(--pico-muted-color);--pico-form-element-active-background-color: #fff;--pico-form-element-active-border-color: var(--pico-primary-border);--pico-form-element-focus-color: var(--pico-primary-border);--pico-form-element-disabled-opacity: .5;--pico-form-element-invalid-border-color: rgb(183.5, 105.5, 106.5);--pico-form-element-invalid-active-border-color: rgb(200.25, 79.25, 72.25);--pico-form-element-invalid-focus-color: var(--pico-form-element-invalid-active-border-color);--pico-form-element-valid-border-color: rgb(76, 154.5, 137.5);--pico-form-element-valid-active-border-color: rgb(39, 152.75, 118.75);--pico-form-element-valid-focus-color: var(--pico-form-element-valid-active-border-color);--pico-switch-background-color: #bfc7d9;--pico-switch-checked-background-color: var(--pico-primary-background);--pico-switch-color: #fff;--pico-switch-thumb-box-shadow: 0 0 0 rgba(0, 0, 0, 0);--pico-range-border-color: #dfe3eb;--pico-range-active-border-color: #bfc7d9;--pico-range-thumb-border-color: var(--pico-background-color);--pico-range-thumb-color: var(--pico-secondary-background);--pico-range-thumb-active-color: var(--pico-primary-background);--pico-accordion-border-color: var(--pico-muted-border-color);--pico-accordion-active-summary-color: var(--pico-primary-hover);--pico-accordion-close-summary-color: var(--pico-color);--pico-accordion-open-summary-color: var(--pico-muted-color);--pico-card-background-color: var(--pico-background-color);--pico-card-border-color: var(--pico-muted-border-color);--pico-card-box-shadow: var(--pico-box-shadow);--pico-card-sectioning-background-color: rgb(251, 251.5, 252.25);--pico-dropdown-background-color: #fff;--pico-dropdown-border-color: #eff1f4;--pico-dropdown-box-shadow: var(--pico-box-shadow);--pico-dropdown-color: var(--pico-color);--pico-dropdown-hover-background-color: #eff1f4;--pico-loading-spinner-opacity: .5;--pico-modal-overlay-background-color: rgba(232, 234, 237, .75);--pico-progress-background-color: #dfe3eb;--pico-progress-color: var(--pico-primary-background);--pico-tooltip-background-color: var(--pico-contrast-background);--pico-tooltip-color: var(--pico-contrast-inverse);--pico-icon-valid: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(76, 154.5, 137.5)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E\");--pico-icon-invalid: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(200.25, 79.25, 72.25)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E\")}[data-theme=light] input:is([type=submit],[type=button],[type=reset],[type=checkbox],[type=radio],[type=file]),:root:not([data-theme=dark]) input:is([type=submit],[type=button],[type=reset],[type=checkbox],[type=radio],[type=file]),:host(:not([data-theme=dark])) input:is([type=submit],[type=button],[type=reset],[type=checkbox],[type=radio],[type=file]){--pico-form-element-focus-color: var(--pico-primary-focus)}@media only screen and (prefers-color-scheme: dark){:root:not([data-theme]),:host(:not([data-theme])){color-scheme:dark;--pico-background-color: rgb(19, 22.5, 30.5);--pico-color: #c2c7d0;--pico-text-selection-color: rgba(1, 170, 255, .1875);--pico-muted-color: #7b8495;--pico-muted-border-color: #202632;--pico-primary: #01aaff;--pico-primary-background: #0172ad;--pico-primary-border: var(--pico-primary-background);--pico-primary-underline: rgba(1, 170, 255, .5);--pico-primary-hover: #79c0ff;--pico-primary-hover-background: #017fc0;--pico-primary-hover-border: var(--pico-primary-hover-background);--pico-primary-hover-underline: var(--pico-primary-hover);--pico-primary-focus: rgba(1, 170, 255, .375);--pico-primary-inverse: #fff;--pico-secondary: #969eaf;--pico-secondary-background: #525f7a;--pico-secondary-border: var(--pico-secondary-background);--pico-secondary-underline: rgba(150, 158, 175, .5);--pico-secondary-hover: #b3b9c5;--pico-secondary-hover-background: #5d6b89;--pico-secondary-hover-border: var(--pico-secondary-hover-background);--pico-secondary-hover-underline: var(--pico-secondary-hover);--pico-secondary-focus: rgba(144, 158, 190, .25);--pico-secondary-inverse: #fff;--pico-contrast: #dfe3eb;--pico-contrast-background: #eff1f4;--pico-contrast-border: var(--pico-contrast-background);--pico-contrast-underline: rgba(223, 227, 235, .5);--pico-contrast-hover: #fff;--pico-contrast-hover-background: #fff;--pico-contrast-hover-border: var(--pico-contrast-hover-background);--pico-contrast-hover-underline: var(--pico-contrast-hover);--pico-contrast-focus: rgba(207, 213, 226, .25);--pico-contrast-inverse: #000;--pico-box-shadow: .0145rem .029rem .174rem rgba(7, 8.5, 12, .01698), .0335rem .067rem .402rem rgba(7, 8.5, 12, .024), .0625rem .125rem .75rem rgba(7, 8.5, 12, .03), .1125rem .225rem 1.35rem rgba(7, 8.5, 12, .036), .2085rem .417rem 2.502rem rgba(7, 8.5, 12, .04302), .5rem 1rem 6rem rgba(7, 8.5, 12, .06), 0 0 0 .0625rem rgba(7, 8.5, 12, .015);--pico-h1-color: #f0f1f3;--pico-h2-color: #e0e3e7;--pico-h3-color: #c2c7d0;--pico-h4-color: #b3b9c5;--pico-h5-color: #a4acba;--pico-h6-color: #8891a4;--pico-mark-background-color: #014063;--pico-mark-color: #fff;--pico-ins-color: #62af9a;--pico-del-color: rgb(205.5, 126, 123);--pico-blockquote-border-color: var(--pico-muted-border-color);--pico-blockquote-footer-color: var(--pico-muted-color);--pico-button-box-shadow: 0 0 0 rgba(0, 0, 0, 0);--pico-button-hover-box-shadow: 0 0 0 rgba(0, 0, 0, 0);--pico-table-border-color: var(--pico-muted-border-color);--pico-table-row-stripped-background-color: rgba(111, 120, 135, .0375);--pico-code-background-color: rgb(26, 30.5, 40.25);--pico-code-color: #8891a4;--pico-code-kbd-background-color: var(--pico-color);--pico-code-kbd-color: var(--pico-background-color);--pico-form-element-background-color: rgb(28, 33, 43.5);--pico-form-element-selected-background-color: #2a3140;--pico-form-element-border-color: #2a3140;--pico-form-element-color: #e0e3e7;--pico-form-element-placeholder-color: #8891a4;--pico-form-element-active-background-color: rgb(26, 30.5, 40.25);--pico-form-element-active-border-color: var(--pico-primary-border);--pico-form-element-focus-color: var(--pico-primary-border);--pico-form-element-disabled-opacity: .5;--pico-form-element-invalid-border-color: rgb(149.5, 74, 80);--pico-form-element-invalid-active-border-color: rgb(183.25, 63.5, 59);--pico-form-element-invalid-focus-color: var(--pico-form-element-invalid-active-border-color);--pico-form-element-valid-border-color: #2a7b6f;--pico-form-element-valid-active-border-color: rgb(22, 137, 105.5);--pico-form-element-valid-focus-color: var(--pico-form-element-valid-active-border-color);--pico-switch-background-color: #333c4e;--pico-switch-checked-background-color: var(--pico-primary-background);--pico-switch-color: #fff;--pico-switch-thumb-box-shadow: 0 0 0 rgba(0, 0, 0, 0);--pico-range-border-color: #202632;--pico-range-active-border-color: #2a3140;--pico-range-thumb-border-color: var(--pico-background-color);--pico-range-thumb-color: var(--pico-secondary-background);--pico-range-thumb-active-color: var(--pico-primary-background);--pico-accordion-border-color: var(--pico-muted-border-color);--pico-accordion-active-summary-color: var(--pico-primary-hover);--pico-accordion-close-summary-color: var(--pico-color);--pico-accordion-open-summary-color: var(--pico-muted-color);--pico-card-background-color: #181c25;--pico-card-border-color: var(--pico-card-background-color);--pico-card-box-shadow: var(--pico-box-shadow);--pico-card-sectioning-background-color: rgb(26, 30.5, 40.25);--pico-dropdown-background-color: #181c25;--pico-dropdown-border-color: #202632;--pico-dropdown-box-shadow: var(--pico-box-shadow);--pico-dropdown-color: var(--pico-color);--pico-dropdown-hover-background-color: #202632;--pico-loading-spinner-opacity: .5;--pico-modal-overlay-background-color: rgba(7.5, 8.5, 10, .75);--pico-progress-background-color: #202632;--pico-progress-color: var(--pico-primary-background);--pico-tooltip-background-color: var(--pico-contrast-background);--pico-tooltip-color: var(--pico-contrast-inverse);--pico-icon-valid: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(42, 123, 111)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E\");--pico-icon-invalid: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(149.5, 74, 80)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E\")}:root:not([data-theme]) input:is([type=submit],[type=button],[type=reset],[type=checkbox],[type=radio],[type=file]),:host(:not([data-theme])) input:is([type=submit],[type=button],[type=reset],[type=checkbox],[type=radio],[type=file]){--pico-form-element-focus-color: var(--pico-primary-focus)}:root:not([data-theme]) details summary[role=button].contrast:not(.outline):after,:host(:not([data-theme])) details summary[role=button].contrast:not(.outline):after{filter:brightness(0)}:root:not([data-theme]) [aria-busy=true]:not(input,select,textarea).contrast:is(button,[type=submit],[type=button],[type=reset],[role=button]):not(.outline):before,:host(:not([data-theme])) [aria-busy=true]:not(input,select,textarea).contrast:is(button,[type=submit],[type=button],[type=reset],[role=button]):not(.outline):before{filter:brightness(0)}}[data-theme=dark]{color-scheme:dark;--pico-background-color: rgb(19, 22.5, 30.5);--pico-color: #c2c7d0;--pico-text-selection-color: rgba(1, 170, 255, .1875);--pico-muted-color: #7b8495;--pico-muted-border-color: #202632;--pico-primary: #01aaff;--pico-primary-background: #0172ad;--pico-primary-border: var(--pico-primary-background);--pico-primary-underline: rgba(1, 170, 255, .5);--pico-primary-hover: #79c0ff;--pico-primary-hover-background: #017fc0;--pico-primary-hover-border: var(--pico-primary-hover-background);--pico-primary-hover-underline: var(--pico-primary-hover);--pico-primary-focus: rgba(1, 170, 255, .375);--pico-primary-inverse: #fff;--pico-secondary: #969eaf;--pico-secondary-background: #525f7a;--pico-secondary-border: var(--pico-secondary-background);--pico-secondary-underline: rgba(150, 158, 175, .5);--pico-secondary-hover: #b3b9c5;--pico-secondary-hover-background: #5d6b89;--pico-secondary-hover-border: var(--pico-secondary-hover-background);--pico-secondary-hover-underline: var(--pico-secondary-hover);--pico-secondary-focus: rgba(144, 158, 190, .25);--pico-secondary-inverse: #fff;--pico-contrast: #dfe3eb;--pico-contrast-background: #eff1f4;--pico-contrast-border: var(--pico-contrast-background);--pico-contrast-underline: rgba(223, 227, 235, .5);--pico-contrast-hover: #fff;--pico-contrast-hover-background: #fff;--pico-contrast-hover-border: var(--pico-contrast-hover-background);--pico-contrast-hover-underline: var(--pico-contrast-hover);--pico-contrast-focus: rgba(207, 213, 226, .25);--pico-contrast-inverse: #000;--pico-box-shadow: .0145rem .029rem .174rem rgba(7, 8.5, 12, .01698), .0335rem .067rem .402rem rgba(7, 8.5, 12, .024), .0625rem .125rem .75rem rgba(7, 8.5, 12, .03), .1125rem .225rem 1.35rem rgba(7, 8.5, 12, .036), .2085rem .417rem 2.502rem rgba(7, 8.5, 12, .04302), .5rem 1rem 6rem rgba(7, 8.5, 12, .06), 0 0 0 .0625rem rgba(7, 8.5, 12, .015);--pico-h1-color: #f0f1f3;--pico-h2-color: #e0e3e7;--pico-h3-color: #c2c7d0;--pico-h4-color: #b3b9c5;--pico-h5-color: #a4acba;--pico-h6-color: #8891a4;--pico-mark-background-color: #014063;--pico-mark-color: #fff;--pico-ins-color: #62af9a;--pico-del-color: rgb(205.5, 126, 123);--pico-blockquote-border-color: var(--pico-muted-border-color);--pico-blockquote-footer-color: var(--pico-muted-color);--pico-button-box-shadow: 0 0 0 rgba(0, 0, 0, 0);--pico-button-hover-box-shadow: 0 0 0 rgba(0, 0, 0, 0);--pico-table-border-color: var(--pico-muted-border-color);--pico-table-row-stripped-background-color: rgba(111, 120, 135, .0375);--pico-code-background-color: rgb(26, 30.5, 40.25);--pico-code-color: #8891a4;--pico-code-kbd-background-color: var(--pico-color);--pico-code-kbd-color: var(--pico-background-color);--pico-form-element-background-color: rgb(28, 33, 43.5);--pico-form-element-selected-background-color: #2a3140;--pico-form-element-border-color: #2a3140;--pico-form-element-color: #e0e3e7;--pico-form-element-placeholder-color: #8891a4;--pico-form-element-active-background-color: rgb(26, 30.5, 40.25);--pico-form-element-active-border-color: var(--pico-primary-border);--pico-form-element-focus-color: var(--pico-primary-border);--pico-form-element-disabled-opacity: .5;--pico-form-element-invalid-border-color: rgb(149.5, 74, 80);--pico-form-element-invalid-active-border-color: rgb(183.25, 63.5, 59);--pico-form-element-invalid-focus-color: var(--pico-form-element-invalid-active-border-color);--pico-form-element-valid-border-color: #2a7b6f;--pico-form-element-valid-active-border-color: rgb(22, 137, 105.5);--pico-form-element-valid-focus-color: var(--pico-form-element-valid-active-border-color);--pico-switch-background-color: #333c4e;--pico-switch-checked-background-color: var(--pico-primary-background);--pico-switch-color: #fff;--pico-switch-thumb-box-shadow: 0 0 0 rgba(0, 0, 0, 0);--pico-range-border-color: #202632;--pico-range-active-border-color: #2a3140;--pico-range-thumb-border-color: var(--pico-background-color);--pico-range-thumb-color: var(--pico-secondary-background);--pico-range-thumb-active-color: var(--pico-primary-background);--pico-accordion-border-color: var(--pico-muted-border-color);--pico-accordion-active-summary-color: var(--pico-primary-hover);--pico-accordion-close-summary-color: var(--pico-color);--pico-accordion-open-summary-color: var(--pico-muted-color);--pico-card-background-color: #181c25;--pico-card-border-color: var(--pico-card-background-color);--pico-card-box-shadow: var(--pico-box-shadow);--pico-card-sectioning-background-color: rgb(26, 30.5, 40.25);--pico-dropdown-background-color: #181c25;--pico-dropdown-border-color: #202632;--pico-dropdown-box-shadow: var(--pico-box-shadow);--pico-dropdown-color: var(--pico-color);--pico-dropdown-hover-background-color: #202632;--pico-loading-spinner-opacity: .5;--pico-modal-overlay-background-color: rgba(7.5, 8.5, 10, .75);--pico-progress-background-color: #202632;--pico-progress-color: var(--pico-primary-background);--pico-tooltip-background-color: var(--pico-contrast-background);--pico-tooltip-color: var(--pico-contrast-inverse);--pico-icon-valid: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(42, 123, 111)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E\");--pico-icon-invalid: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(149.5, 74, 80)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E\")}[data-theme=dark] input:is([type=submit],[type=button],[type=reset],[type=checkbox],[type=radio],[type=file]){--pico-form-element-focus-color: var(--pico-primary-focus)}[data-theme=dark] details summary[role=button].contrast:not(.outline):after{filter:brightness(0)}[data-theme=dark] [aria-busy=true]:not(input,select,textarea).contrast:is(button,[type=submit],[type=button],[type=reset],[role=button]):not(.outline):before{filter:brightness(0)}progress,[type=checkbox],[type=radio],[type=range]{accent-color:var(--pico-primary)}*,*:before,*:after{box-sizing:border-box;background-repeat:no-repeat}:before,:after{text-decoration:inherit;vertical-align:inherit}:where(:root),:where(:host){-webkit-tap-highlight-color:transparent;-webkit-text-size-adjust:100%;text-size-adjust:100%;background-color:var(--pico-background-color);color:var(--pico-color);font-weight:var(--pico-font-weight);font-size:var(--pico-font-size);line-height:var(--pico-line-height);font-family:var(--pico-font-family);text-underline-offset:var(--pico-text-underline-offset);text-rendering:optimizeLegibility;overflow-wrap:break-word;tab-size:4}body{width:100%;margin:0}main{display:block}body>header,body>main,body>footer{padding-block:var(--pico-block-spacing-vertical)}section{margin-bottom:var(--pico-block-spacing-vertical)}.container,.container-fluid{width:100%;margin-right:auto;margin-left:auto;padding-right:var(--pico-spacing);padding-left:var(--pico-spacing)}@media (min-width: 576px){.container{max-width:510px;padding-right:0;padding-left:0}}@media (min-width: 768px){.container{max-width:700px}}@media (min-width: 1024px){.container{max-width:950px}}@media (min-width: 1280px){.container{max-width:1200px}}@media (min-width: 1536px){.container{max-width:1450px}}.grid{grid-column-gap:var(--pico-grid-column-gap);grid-row-gap:var(--pico-grid-row-gap);display:grid;grid-template-columns:1fr}@media (min-width: 768px){.grid{grid-template-columns:repeat(auto-fit,minmax(0%,1fr))}}.grid>*{min-width:0}.overflow-auto{overflow:auto}b,strong{font-weight:bolder}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}address,blockquote,dl,ol,p,pre,table,ul{margin-top:0;margin-bottom:var(--pico-typography-spacing-vertical);color:var(--pico-color);font-style:normal;font-weight:var(--pico-font-weight)}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:var(--pico-typography-spacing-vertical);color:var(--pico-color);font-weight:var(--pico-font-weight);font-size:var(--pico-font-size);line-height:var(--pico-line-height);font-family:var(--pico-font-family)}h1{--pico-color: var(--pico-h1-color)}h2{--pico-color: var(--pico-h2-color)}h3{--pico-color: var(--pico-h3-color)}h4{--pico-color: var(--pico-h4-color)}h5{--pico-color: var(--pico-h5-color)}h6{--pico-color: var(--pico-h6-color)}:where(article,address,blockquote,dl,figure,form,ol,p,pre,table,ul)~:is(h1,h2,h3,h4,h5,h6){margin-top:var(--pico-typography-spacing-top)}p{margin-bottom:var(--pico-typography-spacing-vertical)}hgroup{margin-bottom:var(--pico-typography-spacing-vertical)}hgroup>*{margin-top:0;margin-bottom:0}hgroup>*:not(:first-child):last-child{--pico-color: var(--pico-muted-color);--pico-font-weight: unset;font-size:1rem}:where(ol,ul) li{margin-bottom:calc(var(--pico-typography-spacing-vertical) * .25)}:where(dl,ol,ul) :where(dl,ol,ul){margin:0;margin-top:calc(var(--pico-typography-spacing-vertical) * .25)}ul li{list-style:square}mark{padding:.125rem .25rem;background-color:var(--pico-mark-background-color);color:var(--pico-mark-color);vertical-align:baseline}blockquote{display:block;margin:var(--pico-typography-spacing-vertical) 0;padding:var(--pico-spacing);border-right:none;border-left:.25rem solid var(--pico-blockquote-border-color);border-inline-start:.25rem solid var(--pico-blockquote-border-color);border-inline-end:none}blockquote footer{margin-top:calc(var(--pico-typography-spacing-vertical) * .5);color:var(--pico-blockquote-footer-color)}abbr[title]{border-bottom:1px dotted;text-decoration:none;cursor:help}ins{color:var(--pico-ins-color);text-decoration:none}del{color:var(--pico-del-color)}::selection{background-color:var(--pico-text-selection-color)}:where(a:not([role=button])),[role=link]{--pico-color: var(--pico-primary);--pico-background-color: transparent;--pico-underline: var(--pico-primary-underline);outline:none;background-color:var(--pico-background-color);color:var(--pico-color);text-decoration:var(--pico-text-decoration);text-decoration-color:var(--pico-underline);text-underline-offset:.125em;transition:background-color var(--pico-transition),color var(--pico-transition),text-decoration var(--pico-transition),box-shadow var(--pico-transition)}:where(a:not([role=button])):is([aria-current]:not([aria-current=false]),:hover,:active,:focus),[role=link]:is([aria-current]:not([aria-current=false]),:hover,:active,:focus){--pico-color: var(--pico-primary-hover);--pico-underline: var(--pico-primary-hover-underline);--pico-text-decoration: underline}:where(a:not([role=button])):focus-visible,[role=link]:focus-visible{box-shadow:0 0 0 var(--pico-outline-width) var(--pico-primary-focus)}:where(a:not([role=button])).secondary,[role=link].secondary{--pico-color: var(--pico-secondary);--pico-underline: var(--pico-secondary-underline)}:where(a:not([role=button])).secondary:is([aria-current]:not([aria-current=false]),:hover,:active,:focus),[role=link].secondary:is([aria-current]:not([aria-current=false]),:hover,:active,:focus){--pico-color: var(--pico-secondary-hover);--pico-underline: var(--pico-secondary-hover-underline)}:where(a:not([role=button])).contrast,[role=link].contrast{--pico-color: var(--pico-contrast);--pico-underline: var(--pico-contrast-underline)}:where(a:not([role=button])).contrast:is([aria-current]:not([aria-current=false]),:hover,:active,:focus),[role=link].contrast:is([aria-current]:not([aria-current=false]),:hover,:active,:focus){--pico-color: var(--pico-contrast-hover);--pico-underline: var(--pico-contrast-hover-underline)}a[role=button]{display:inline-block}button{margin:0;overflow:visible;font-family:inherit;text-transform:none}button,[type=submit],[type=reset],[type=button]{-webkit-appearance:button}button,[type=submit],[type=reset],[type=button],[type=file]::file-selector-button,[role=button]{--pico-background-color: var(--pico-primary-background);--pico-border-color: var(--pico-primary-border);--pico-color: var(--pico-primary-inverse);--pico-box-shadow: var(--pico-button-box-shadow, 0 0 0 rgba(0, 0, 0, 0));padding:var(--pico-form-element-spacing-vertical) var(--pico-form-element-spacing-horizontal);border:var(--pico-border-width) solid var(--pico-border-color);border-radius:var(--pico-border-radius);outline:none;background-color:var(--pico-background-color);box-shadow:var(--pico-box-shadow);color:var(--pico-color);font-weight:var(--pico-font-weight);font-size:1rem;line-height:var(--pico-line-height);text-align:center;text-decoration:none;cursor:pointer;-webkit-user-select:none;user-select:none;transition:background-color var(--pico-transition),border-color var(--pico-transition),color var(--pico-transition),box-shadow var(--pico-transition)}button:is([aria-current]:not([aria-current=false])),button:is(:hover,:active,:focus),[type=submit]:is([aria-current]:not([aria-current=false])),[type=submit]:is(:hover,:active,:focus),[type=reset]:is([aria-current]:not([aria-current=false])),[type=reset]:is(:hover,:active,:focus),[type=button]:is([aria-current]:not([aria-current=false])),[type=button]:is(:hover,:active,:focus),[type=file]::file-selector-button:is([aria-current]:not([aria-current=false])),[type=file]::file-selector-button:is(:hover,:active,:focus),[role=button]:is([aria-current]:not([aria-current=false])),[role=button]:is(:hover,:active,:focus){--pico-background-color: var(--pico-primary-hover-background);--pico-border-color: var(--pico-primary-hover-border);--pico-box-shadow: var(--pico-button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0));--pico-color: var(--pico-primary-inverse)}button:focus,button:is([aria-current]:not([aria-current=false])):focus,[type=submit]:focus,[type=submit]:is([aria-current]:not([aria-current=false])):focus,[type=reset]:focus,[type=reset]:is([aria-current]:not([aria-current=false])):focus,[type=button]:focus,[type=button]:is([aria-current]:not([aria-current=false])):focus,[type=file]::file-selector-button:focus,[type=file]::file-selector-button:is([aria-current]:not([aria-current=false])):focus,[role=button]:focus,[role=button]:is([aria-current]:not([aria-current=false])):focus{--pico-box-shadow: var(--pico-button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)), 0 0 0 var(--pico-outline-width) var(--pico-primary-focus)}[type=submit],[type=reset],[type=button]{margin-bottom:var(--pico-spacing)}:is(button,[type=submit],[type=button],[role=button]).secondary,[type=reset],[type=file]::file-selector-button{--pico-background-color: var(--pico-secondary-background);--pico-border-color: var(--pico-secondary-border);--pico-color: var(--pico-secondary-inverse);cursor:pointer}:is(button,[type=submit],[type=button],[role=button]).secondary:is([aria-current]:not([aria-current=false]),:hover,:active,:focus),[type=reset]:is([aria-current]:not([aria-current=false]),:hover,:active,:focus),[type=file]::file-selector-button:is([aria-current]:not([aria-current=false]),:hover,:active,:focus){--pico-background-color: var(--pico-secondary-hover-background);--pico-border-color: var(--pico-secondary-hover-border);--pico-color: var(--pico-secondary-inverse)}:is(button,[type=submit],[type=button],[role=button]).secondary:focus,:is(button,[type=submit],[type=button],[role=button]).secondary:is([aria-current]:not([aria-current=false])):focus,[type=reset]:focus,[type=reset]:is([aria-current]:not([aria-current=false])):focus,[type=file]::file-selector-button:focus,[type=file]::file-selector-button:is([aria-current]:not([aria-current=false])):focus{--pico-box-shadow: var(--pico-button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)), 0 0 0 var(--pico-outline-width) var(--pico-secondary-focus)}:is(button,[type=submit],[type=button],[role=button]).contrast{--pico-background-color: var(--pico-contrast-background);--pico-border-color: var(--pico-contrast-border);--pico-color: var(--pico-contrast-inverse)}:is(button,[type=submit],[type=button],[role=button]).contrast:is([aria-current]:not([aria-current=false]),:hover,:active,:focus){--pico-background-color: var(--pico-contrast-hover-background);--pico-border-color: var(--pico-contrast-hover-border);--pico-color: var(--pico-contrast-inverse)}:is(button,[type=submit],[type=button],[role=button]).contrast:focus,:is(button,[type=submit],[type=button],[role=button]).contrast:is([aria-current]:not([aria-current=false])):focus{--pico-box-shadow: var(--pico-button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)), 0 0 0 var(--pico-outline-width) var(--pico-contrast-focus)}:is(button,[type=submit],[type=button],[role=button]).outline,[type=reset].outline{--pico-background-color: transparent;--pico-color: var(--pico-primary);--pico-border-color: var(--pico-primary)}:is(button,[type=submit],[type=button],[role=button]).outline:is([aria-current]:not([aria-current=false]),:hover,:active,:focus),[type=reset].outline:is([aria-current]:not([aria-current=false]),:hover,:active,:focus){--pico-background-color: transparent;--pico-color: var(--pico-primary-hover);--pico-border-color: var(--pico-primary-hover)}:is(button,[type=submit],[type=button],[role=button]).outline.secondary,[type=reset].outline{--pico-color: var(--pico-secondary);--pico-border-color: var(--pico-secondary)}:is(button,[type=submit],[type=button],[role=button]).outline.secondary:is([aria-current]:not([aria-current=false]),:hover,:active,:focus),[type=reset].outline:is([aria-current]:not([aria-current=false]),:hover,:active,:focus){--pico-color: var(--pico-secondary-hover);--pico-border-color: var(--pico-secondary-hover)}:is(button,[type=submit],[type=button],[role=button]).outline.contrast{--pico-color: var(--pico-contrast);--pico-border-color: var(--pico-contrast)}:is(button,[type=submit],[type=button],[role=button]).outline.contrast:is([aria-current]:not([aria-current=false]),:hover,:active,:focus){--pico-color: var(--pico-contrast-hover);--pico-border-color: var(--pico-contrast-hover)}:where(button,[type=submit],[type=reset],[type=button],[role=button])[disabled],:where(fieldset[disabled]) :is(button,[type=submit],[type=button],[type=reset],[role=button]){opacity:.5;pointer-events:none}:where(table){width:100%;border-collapse:collapse;border-spacing:0;text-indent:0}th,td{padding:calc(var(--pico-spacing) / 2) var(--pico-spacing);border-bottom:var(--pico-border-width) solid var(--pico-table-border-color);background-color:var(--pico-background-color);color:var(--pico-color);font-weight:var(--pico-font-weight);text-align:left;text-align:start}tfoot th,tfoot td{border-top:var(--pico-border-width) solid var(--pico-table-border-color);border-bottom:0}table.striped tbody tr:nth-child(odd) th,table.striped tbody tr:nth-child(odd) td{background-color:var(--pico-table-row-stripped-background-color)}:where(audio,canvas,iframe,img,svg,video){vertical-align:middle}audio,video{display:inline-block}audio:not([controls]){display:none;height:0}:where(iframe){border-style:none}img{max-width:100%;height:auto;border-style:none}:where(svg:not([fill])){fill:currentColor}svg:not(:root),svg:not(:host){overflow:hidden}pre,code,kbd,samp{font-size:.875em;font-family:var(--pico-font-family)}pre code,pre samp{font-size:inherit;font-family:inherit}pre{-ms-overflow-style:scrollbar;overflow:auto}pre,code,kbd,samp{border-radius:var(--pico-border-radius);background:var(--pico-code-background-color);color:var(--pico-code-color);font-weight:var(--pico-font-weight);line-height:initial}code,kbd,samp{display:inline-block;padding:.375rem}pre{display:block;margin-bottom:var(--pico-spacing);overflow-x:auto}pre>code,pre>samp{display:block;padding:var(--pico-spacing);background:none;line-height:var(--pico-line-height)}kbd{background-color:var(--pico-code-kbd-background-color);color:var(--pico-code-kbd-color);vertical-align:baseline}figure{display:block;margin:0;padding:0}figure figcaption{padding:calc(var(--pico-spacing) * .5) 0;color:var(--pico-muted-color)}hr{height:0;margin:var(--pico-typography-spacing-vertical) 0;border:0;border-top:1px solid var(--pico-muted-border-color);color:inherit}[hidden],template{display:none!important}canvas{display:inline-block}input,optgroup,select,textarea{margin:0;font-size:1rem;line-height:var(--pico-line-height);font-family:inherit;letter-spacing:inherit}input{overflow:visible}select{text-transform:none}legend{max-width:100%;padding:0;color:inherit;white-space:normal}textarea{overflow:auto}[type=checkbox],[type=radio]{padding:0}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}::-moz-focus-inner{padding:0;border-style:none}:-moz-focusring{outline:none}:-moz-ui-invalid{box-shadow:none}::-ms-expand{display:none}[type=file],[type=range]{padding:0;border-width:0}input:not([type=checkbox],[type=radio],[type=range]){height:calc(1rem * var(--pico-line-height) + var(--pico-form-element-spacing-vertical) * 2 + var(--pico-border-width) * 2)}fieldset{width:100%;margin:0;margin-bottom:var(--pico-spacing);padding:0;border:0}label,fieldset legend{display:block;margin-bottom:calc(var(--pico-spacing) * .375);color:var(--pico-color);font-weight:var(--pico-form-label-font-weight, var(--pico-font-weight))}fieldset legend{margin-bottom:calc(var(--pico-spacing) * .5)}input:not([type=checkbox],[type=radio]),button[type=submit],select,textarea{width:100%}input:not([type=checkbox],[type=radio],[type=range],[type=file]),select,textarea{appearance:none;padding:var(--pico-form-element-spacing-vertical) var(--pico-form-element-spacing-horizontal)}input,select,textarea{--pico-background-color: var(--pico-form-element-background-color);--pico-border-color: var(--pico-form-element-border-color);--pico-color: var(--pico-form-element-color);--pico-box-shadow: none;border:var(--pico-border-width) solid var(--pico-border-color);border-radius:var(--pico-border-radius);outline:none;background-color:var(--pico-background-color);box-shadow:var(--pico-box-shadow);color:var(--pico-color);font-weight:var(--pico-font-weight);transition:background-color var(--pico-transition),border-color var(--pico-transition),color var(--pico-transition),box-shadow var(--pico-transition)}input:not([type=submit],[type=button],[type=reset],[type=checkbox],[type=radio],[readonly]):is(:active,:focus),:where(select,textarea):not([readonly]):is(:active,:focus){--pico-background-color: var(--pico-form-element-active-background-color)}input:not([type=submit],[type=button],[type=reset],[role=switch],[readonly]):is(:active,:focus),:where(select,textarea):not([readonly]):is(:active,:focus){--pico-border-color: var(--pico-form-element-active-border-color)}input:not([type=submit],[type=button],[type=reset],[type=range],[type=file],[readonly]):focus,:where(select,textarea):not([readonly]):focus{--pico-box-shadow: 0 0 0 var(--pico-outline-width) var(--pico-form-element-focus-color)}input:not([type=submit],[type=button],[type=reset])[disabled],select[disabled],textarea[disabled],label[aria-disabled=true],:where(fieldset[disabled]) :is(input:not([type=submit],[type=button],[type=reset]),select,textarea){opacity:var(--pico-form-element-disabled-opacity);pointer-events:none}label[aria-disabled=true] input[disabled]{opacity:1}:where(input,select,textarea):not([type=checkbox],[type=radio],[type=date],[type=datetime-local],[type=month],[type=time],[type=week],[type=range])[aria-invalid]{padding-right:calc(var(--pico-form-element-spacing-horizontal) + 1.5rem)!important;padding-left:var(--pico-form-element-spacing-horizontal);padding-inline-start:var(--pico-form-element-spacing-horizontal)!important;padding-inline-end:calc(var(--pico-form-element-spacing-horizontal) + 1.5rem)!important;background-position:center right .75rem;background-size:1rem auto;background-repeat:no-repeat}:where(input,select,textarea):not([type=checkbox],[type=radio],[type=date],[type=datetime-local],[type=month],[type=time],[type=week],[type=range])[aria-invalid=false]:not(select){background-image:var(--pico-icon-valid)}:where(input,select,textarea):not([type=checkbox],[type=radio],[type=date],[type=datetime-local],[type=month],[type=time],[type=week],[type=range])[aria-invalid=true]:not(select){background-image:var(--pico-icon-invalid)}:where(input,select,textarea)[aria-invalid=false]{--pico-border-color: var(--pico-form-element-valid-border-color)}:where(input,select,textarea)[aria-invalid=false]:is(:active,:focus){--pico-border-color: var(--pico-form-element-valid-active-border-color) !important}:where(input,select,textarea)[aria-invalid=false]:is(:active,:focus):not([type=checkbox],[type=radio]){--pico-box-shadow: 0 0 0 var(--pico-outline-width) var(--pico-form-element-valid-focus-color) !important}:where(input,select,textarea)[aria-invalid=true]{--pico-border-color: var(--pico-form-element-invalid-border-color)}:where(input,select,textarea)[aria-invalid=true]:is(:active,:focus){--pico-border-color: var(--pico-form-element-invalid-active-border-color) !important}:where(input,select,textarea)[aria-invalid=true]:is(:active,:focus):not([type=checkbox],[type=radio]){--pico-box-shadow: 0 0 0 var(--pico-outline-width) var(--pico-form-element-invalid-focus-color) !important}[dir=rtl] :where(input,select,textarea):not([type=checkbox],[type=radio]):is([aria-invalid],[aria-invalid=true],[aria-invalid=false]){background-position:center left .75rem}input::placeholder,input::-webkit-input-placeholder,textarea::placeholder,textarea::-webkit-input-placeholder,select:invalid{color:var(--pico-form-element-placeholder-color);opacity:1}input:not([type=checkbox],[type=radio]),select,textarea{margin-bottom:var(--pico-spacing)}select::-ms-expand{border:0;background-color:transparent}select:not([multiple],[size]){padding-right:calc(var(--pico-form-element-spacing-horizontal) + 1.5rem);padding-left:var(--pico-form-element-spacing-horizontal);padding-inline-start:var(--pico-form-element-spacing-horizontal);padding-inline-end:calc(var(--pico-form-element-spacing-horizontal) + 1.5rem);background-image:var(--pico-icon-chevron);background-position:center right .75rem;background-size:1rem auto;background-repeat:no-repeat}select[multiple] option:checked{background:var(--pico-form-element-selected-background-color);color:var(--pico-form-element-color)}[dir=rtl] select:not([multiple],[size]){background-position:center left .75rem}textarea{display:block;resize:vertical}textarea[aria-invalid]{--pico-icon-height: calc(1rem * var(--pico-line-height) + var(--pico-form-element-spacing-vertical) * 2 + var(--pico-border-width) * 2);background-position:top right .75rem!important;background-size:1rem var(--pico-icon-height)!important}:where(input,select,textarea,fieldset,.grid)+small{display:block;width:100%;margin-top:calc(var(--pico-spacing) * -.75);margin-bottom:var(--pico-spacing);color:var(--pico-muted-color)}:where(input,select,textarea,fieldset,.grid)[aria-invalid=false]+small{color:var(--pico-ins-color)}:where(input,select,textarea,fieldset,.grid)[aria-invalid=true]+small{color:var(--pico-del-color)}label>:where(input,select,textarea){margin-top:calc(var(--pico-spacing) * .25)}label:has([type=checkbox],[type=radio]){width:fit-content;cursor:pointer}[type=checkbox],[type=radio]{-webkit-appearance:none;-moz-appearance:none;appearance:none;width:1.25em;height:1.25em;margin-top:-.125em;margin-inline-end:.5em;border-width:var(--pico-border-width);vertical-align:middle;cursor:pointer}[type=checkbox]::-ms-check,[type=radio]::-ms-check{display:none}[type=checkbox]:checked,[type=checkbox]:checked:active,[type=checkbox]:checked:focus,[type=radio]:checked,[type=radio]:checked:active,[type=radio]:checked:focus{--pico-background-color: var(--pico-primary-background);--pico-border-color: var(--pico-primary-border);background-image:var(--pico-icon-checkbox);background-position:center;background-size:.75em auto;background-repeat:no-repeat}[type=checkbox]~label,[type=radio]~label{display:inline-block;margin-bottom:0;cursor:pointer}[type=checkbox]~label:not(:last-of-type),[type=radio]~label:not(:last-of-type){margin-inline-end:1em}[type=checkbox]:indeterminate{--pico-background-color: var(--pico-primary-background);--pico-border-color: var(--pico-primary-border);background-image:var(--pico-icon-minus);background-position:center;background-size:.75em auto;background-repeat:no-repeat}[type=radio]{border-radius:50%}[type=radio]:checked,[type=radio]:checked:active,[type=radio]:checked:focus{--pico-background-color: var(--pico-primary-inverse);border-width:.35em;background-image:none}[type=checkbox][role=switch]{--pico-background-color: var(--pico-switch-background-color);--pico-color: var(--pico-switch-color);width:2.25em;height:1.25em;border:var(--pico-border-width) solid var(--pico-border-color);border-radius:1.25em;background-color:var(--pico-background-color);line-height:1.25em}[type=checkbox][role=switch]:not([aria-invalid]){--pico-border-color: var(--pico-switch-background-color)}[type=checkbox][role=switch]:before{display:block;aspect-ratio:1;height:100%;border-radius:50%;background-color:var(--pico-color);box-shadow:var(--pico-switch-thumb-box-shadow);content:\"\";transition:margin .1s ease-in-out}[type=checkbox][role=switch]:focus{--pico-background-color: var(--pico-switch-background-color);--pico-border-color: var(--pico-switch-background-color)}[type=checkbox][role=switch]:checked{--pico-background-color: var(--pico-switch-checked-background-color);--pico-border-color: var(--pico-switch-checked-background-color);background-image:none}[type=checkbox][role=switch]:checked:before{margin-inline-start:1em}[type=checkbox][role=switch][disabled]{--pico-background-color: var(--pico-border-color)}[type=checkbox][aria-invalid=false]:checked,[type=checkbox][aria-invalid=false]:checked:active,[type=checkbox][aria-invalid=false]:checked:focus,[type=checkbox][role=switch][aria-invalid=false]:checked,[type=checkbox][role=switch][aria-invalid=false]:checked:active,[type=checkbox][role=switch][aria-invalid=false]:checked:focus{--pico-background-color: var(--pico-form-element-valid-border-color)}[type=checkbox]:checked[aria-invalid=true],[type=checkbox]:checked:active[aria-invalid=true],[type=checkbox]:checked:focus[aria-invalid=true],[type=checkbox][role=switch]:checked[aria-invalid=true],[type=checkbox][role=switch]:checked:active[aria-invalid=true],[type=checkbox][role=switch]:checked:focus[aria-invalid=true]{--pico-background-color: var(--pico-form-element-invalid-border-color)}[type=checkbox][aria-invalid=false]:checked,[type=checkbox][aria-invalid=false]:checked:active,[type=checkbox][aria-invalid=false]:checked:focus,[type=radio][aria-invalid=false]:checked,[type=radio][aria-invalid=false]:checked:active,[type=radio][aria-invalid=false]:checked:focus,[type=checkbox][role=switch][aria-invalid=false]:checked,[type=checkbox][role=switch][aria-invalid=false]:checked:active,[type=checkbox][role=switch][aria-invalid=false]:checked:focus{--pico-border-color: var(--pico-form-element-valid-border-color)}[type=checkbox]:checked[aria-invalid=true],[type=checkbox]:checked:active[aria-invalid=true],[type=checkbox]:checked:focus[aria-invalid=true],[type=radio]:checked[aria-invalid=true],[type=radio]:checked:active[aria-invalid=true],[type=radio]:checked:focus[aria-invalid=true],[type=checkbox][role=switch]:checked[aria-invalid=true],[type=checkbox][role=switch]:checked:active[aria-invalid=true],[type=checkbox][role=switch]:checked:focus[aria-invalid=true]{--pico-border-color: var(--pico-form-element-invalid-border-color)}[type=color]::-webkit-color-swatch-wrapper{padding:0}[type=color]::-moz-focus-inner{padding:0}[type=color]::-webkit-color-swatch{border:0;border-radius:calc(var(--pico-border-radius) * .5)}[type=color]::-moz-color-swatch{border:0;border-radius:calc(var(--pico-border-radius) * .5)}input:not([type=checkbox],[type=radio],[type=range],[type=file]):is([type=date],[type=datetime-local],[type=month],[type=time],[type=week]){--pico-icon-position: .75rem;--pico-icon-width: 1rem;padding-right:calc(var(--pico-icon-width) + var(--pico-icon-position));background-image:var(--pico-icon-date);background-position:center right var(--pico-icon-position);background-size:var(--pico-icon-width) auto;background-repeat:no-repeat}input:not([type=checkbox],[type=radio],[type=range],[type=file])[type=time]{background-image:var(--pico-icon-time)}[type=date]::-webkit-calendar-picker-indicator,[type=datetime-local]::-webkit-calendar-picker-indicator,[type=month]::-webkit-calendar-picker-indicator,[type=time]::-webkit-calendar-picker-indicator,[type=week]::-webkit-calendar-picker-indicator{width:var(--pico-icon-width);margin-right:calc(var(--pico-icon-width) * -1);margin-left:var(--pico-icon-position);opacity:0}@-moz-document url-prefix(){[type=date],[type=datetime-local],[type=month],[type=time],[type=week]{padding-right:var(--pico-form-element-spacing-horizontal)!important;background-image:none!important}}[dir=rtl] :is([type=date],[type=datetime-local],[type=month],[type=time],[type=week]){text-align:right}[type=file]{--pico-color: var(--pico-muted-color);margin-left:calc(var(--pico-outline-width) * -1);padding:calc(var(--pico-form-element-spacing-vertical) * .5) 0;padding-left:var(--pico-outline-width);border:0;border-radius:0;background:none}[type=file]::file-selector-button{margin-right:calc(var(--pico-spacing) / 2);padding:calc(var(--pico-form-element-spacing-vertical) * .5) var(--pico-form-element-spacing-horizontal)}[type=file]:is(:hover,:active,:focus)::file-selector-button{--pico-background-color: var(--pico-secondary-hover-background);--pico-border-color: var(--pico-secondary-hover-border)}[type=file]:focus::file-selector-button{--pico-box-shadow: var(--pico-button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)), 0 0 0 var(--pico-outline-width) var(--pico-secondary-focus)}[type=range]{-webkit-appearance:none;-moz-appearance:none;appearance:none;width:100%;height:1.25rem;background:none}[type=range]::-webkit-slider-runnable-track{width:100%;height:.375rem;border-radius:var(--pico-border-radius);background-color:var(--pico-range-border-color);transition:background-color var(--pico-transition),box-shadow var(--pico-transition)}[type=range]::-moz-range-track{width:100%;height:.375rem;border-radius:var(--pico-border-radius);background-color:var(--pico-range-border-color);transition:background-color var(--pico-transition),box-shadow var(--pico-transition)}[type=range]::-ms-track{width:100%;height:.375rem;border-radius:var(--pico-border-radius);background-color:var(--pico-range-border-color);transition:background-color var(--pico-transition),box-shadow var(--pico-transition)}[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:1.25rem;height:1.25rem;margin-top:-.4375rem;border:2px solid var(--pico-range-thumb-border-color);border-radius:50%;background-color:var(--pico-range-thumb-color);cursor:pointer;transition:background-color var(--pico-transition),transform var(--pico-transition)}[type=range]::-moz-range-thumb{-webkit-appearance:none;width:1.25rem;height:1.25rem;margin-top:-.4375rem;border:2px solid var(--pico-range-thumb-border-color);border-radius:50%;background-color:var(--pico-range-thumb-color);cursor:pointer;transition:background-color var(--pico-transition),transform var(--pico-transition)}[type=range]::-ms-thumb{-webkit-appearance:none;width:1.25rem;height:1.25rem;margin-top:-.4375rem;border:2px solid var(--pico-range-thumb-border-color);border-radius:50%;background-color:var(--pico-range-thumb-color);cursor:pointer;transition:background-color var(--pico-transition),transform var(--pico-transition)}[type=range]:active,[type=range]:focus-within{--pico-range-border-color: var(--pico-range-active-border-color);--pico-range-thumb-color: var(--pico-range-thumb-active-color)}[type=range]:active::-webkit-slider-thumb{transform:scale(1.25)}[type=range]:active::-moz-range-thumb{transform:scale(1.25)}[type=range]:active::-ms-thumb{transform:scale(1.25)}input:not([type=checkbox],[type=radio],[type=range],[type=file])[type=search]{padding-inline-start:calc(var(--pico-form-element-spacing-horizontal) + 1.75rem);background-image:var(--pico-icon-search);background-position:center left calc(var(--pico-form-element-spacing-horizontal) + .125rem);background-size:1rem auto;background-repeat:no-repeat}input:not([type=checkbox],[type=radio],[type=range],[type=file])[type=search][aria-invalid]{padding-inline-start:calc(var(--pico-form-element-spacing-horizontal) + 1.75rem)!important;background-position:center left 1.125rem,center right .75rem}input:not([type=checkbox],[type=radio],[type=range],[type=file])[type=search][aria-invalid=false]{background-image:var(--pico-icon-search),var(--pico-icon-valid)}input:not([type=checkbox],[type=radio],[type=range],[type=file])[type=search][aria-invalid=true]{background-image:var(--pico-icon-search),var(--pico-icon-invalid)}[dir=rtl] :where(input):not([type=checkbox],[type=radio],[type=range],[type=file])[type=search]{background-position:center right 1.125rem}[dir=rtl] :where(input):not([type=checkbox],[type=radio],[type=range],[type=file])[type=search][aria-invalid]{background-position:center right 1.125rem,center left .75rem}details{display:block;margin-bottom:var(--pico-spacing)}details summary{line-height:1rem;list-style-type:none;cursor:pointer;transition:color var(--pico-transition)}details summary:not([role]){color:var(--pico-accordion-close-summary-color)}details summary::-webkit-details-marker{display:none}details summary::marker{display:none}details summary::-moz-list-bullet{list-style-type:none}details summary:after{display:block;width:1rem;height:1rem;margin-inline-start:calc(var(--pico-spacing, 1rem) * .5);float:right;transform:rotate(-90deg);background-image:var(--pico-icon-chevron);background-position:right center;background-size:1rem auto;background-repeat:no-repeat;content:\"\";transition:transform var(--pico-transition)}details summary:focus{outline:none}details summary:focus:not([role]){color:var(--pico-accordion-active-summary-color)}details summary:focus-visible:not([role]){outline:var(--pico-outline-width) solid var(--pico-primary-focus);outline-offset:calc(var(--pico-spacing, 1rem) * .5);color:var(--pico-primary)}details summary[role=button]{width:100%;text-align:left}details summary[role=button]:after{height:calc(1rem * var(--pico-line-height, 1.5))}details[open]>summary{margin-bottom:var(--pico-spacing)}details[open]>summary:not([role]):not(:focus){color:var(--pico-accordion-open-summary-color)}details[open]>summary:after{transform:rotate(0)}[dir=rtl] details summary{text-align:right}[dir=rtl] details summary:after{float:left;background-position:left center}article{margin-bottom:var(--pico-block-spacing-vertical);padding:var(--pico-block-spacing-vertical) var(--pico-block-spacing-horizontal);border-radius:var(--pico-border-radius);background:var(--pico-card-background-color);box-shadow:var(--pico-card-box-shadow)}article>header,article>footer{margin-right:calc(var(--pico-block-spacing-horizontal) * -1);margin-left:calc(var(--pico-block-spacing-horizontal) * -1);padding:calc(var(--pico-block-spacing-vertical) * .66) var(--pico-block-spacing-horizontal);background-color:var(--pico-card-sectioning-background-color)}article>header{margin-top:calc(var(--pico-block-spacing-vertical) * -1);margin-bottom:var(--pico-block-spacing-vertical);border-bottom:var(--pico-border-width) solid var(--pico-card-border-color);border-top-right-radius:var(--pico-border-radius);border-top-left-radius:var(--pico-border-radius)}article>footer{margin-top:var(--pico-block-spacing-vertical);margin-bottom:calc(var(--pico-block-spacing-vertical) * -1);border-top:var(--pico-border-width) solid var(--pico-card-border-color);border-bottom-right-radius:var(--pico-border-radius);border-bottom-left-radius:var(--pico-border-radius)}details.dropdown{position:relative;border-bottom:none}details.dropdown>summary:after,details.dropdown>button:after,details.dropdown>a:after{display:block;width:1rem;height:calc(1rem * var(--pico-line-height, 1.5));margin-inline-start:.25rem;float:right;transform:rotate(0) translate(.2rem);background-image:var(--pico-icon-chevron);background-position:right center;background-size:1rem auto;background-repeat:no-repeat;content:\"\"}nav details.dropdown{margin-bottom:0}details.dropdown>summary:not([role]){height:calc(1rem * var(--pico-line-height) + var(--pico-form-element-spacing-vertical) * 2 + var(--pico-border-width) * 2);padding:var(--pico-form-element-spacing-vertical) var(--pico-form-element-spacing-horizontal);border:var(--pico-border-width) solid var(--pico-form-element-border-color);border-radius:var(--pico-border-radius);background-color:var(--pico-form-element-background-color);color:var(--pico-form-element-placeholder-color);line-height:inherit;cursor:pointer;-webkit-user-select:none;user-select:none;transition:background-color var(--pico-transition),border-color var(--pico-transition),color var(--pico-transition),box-shadow var(--pico-transition)}details.dropdown>summary:not([role]):active,details.dropdown>summary:not([role]):focus{border-color:var(--pico-form-element-active-border-color);background-color:var(--pico-form-element-active-background-color)}details.dropdown>summary:not([role]):focus{box-shadow:0 0 0 var(--pico-outline-width) var(--pico-form-element-focus-color)}details.dropdown>summary:not([role]):focus-visible{outline:none}details.dropdown>summary:not([role])[aria-invalid=false]{--pico-form-element-border-color: var(--pico-form-element-valid-border-color);--pico-form-element-active-border-color: var(--pico-form-element-valid-focus-color);--pico-form-element-focus-color: var(--pico-form-element-valid-focus-color)}details.dropdown>summary:not([role])[aria-invalid=true]{--pico-form-element-border-color: var(--pico-form-element-invalid-border-color);--pico-form-element-active-border-color: var(--pico-form-element-invalid-focus-color);--pico-form-element-focus-color: var(--pico-form-element-invalid-focus-color)}nav details.dropdown{display:inline;margin:calc(var(--pico-nav-element-spacing-vertical) * -1) 0}nav details.dropdown>summary:after{transform:rotate(0) translate(0)}nav details.dropdown>summary:not([role]){height:calc(1rem * var(--pico-line-height) + var(--pico-nav-link-spacing-vertical) * 2);padding:calc(var(--pico-nav-link-spacing-vertical) - var(--pico-border-width) * 2) var(--pico-nav-link-spacing-horizontal)}nav details.dropdown>summary:not([role]):focus-visible{box-shadow:0 0 0 var(--pico-outline-width) var(--pico-primary-focus)}details.dropdown>summary+ul{display:flex;z-index:99;position:absolute;left:0;flex-direction:column;width:100%;min-width:fit-content;margin:0;margin-top:var(--pico-outline-width);padding:0;border:var(--pico-border-width) solid var(--pico-dropdown-border-color);border-radius:var(--pico-border-radius);background-color:var(--pico-dropdown-background-color);box-shadow:var(--pico-dropdown-box-shadow);color:var(--pico-dropdown-color);white-space:nowrap;opacity:0;transition:opacity var(--pico-transition),transform 0s ease-in-out 1s}details.dropdown>summary+ul[dir=rtl]{right:0;left:auto}details.dropdown>summary+ul li{width:100%;margin-bottom:0;padding:calc(var(--pico-form-element-spacing-vertical) * .5) var(--pico-form-element-spacing-horizontal);list-style:none}details.dropdown>summary+ul li:first-of-type{margin-top:calc(var(--pico-form-element-spacing-vertical) * .5)}details.dropdown>summary+ul li:last-of-type{margin-bottom:calc(var(--pico-form-element-spacing-vertical) * .5)}details.dropdown>summary+ul li a{display:block;margin:calc(var(--pico-form-element-spacing-vertical) * -.5) calc(var(--pico-form-element-spacing-horizontal) * -1);padding:calc(var(--pico-form-element-spacing-vertical) * .5) var(--pico-form-element-spacing-horizontal);overflow:hidden;border-radius:0;color:var(--pico-dropdown-color);text-decoration:none;text-overflow:ellipsis}details.dropdown>summary+ul li a:hover,details.dropdown>summary+ul li a:focus,details.dropdown>summary+ul li a:active,details.dropdown>summary+ul li a:focus-visible,details.dropdown>summary+ul li a[aria-current]:not([aria-current=false]){background-color:var(--pico-dropdown-hover-background-color)}details.dropdown>summary+ul li label{width:100%}details.dropdown>summary+ul li:has(label):hover{background-color:var(--pico-dropdown-hover-background-color)}details.dropdown[open]>summary{margin-bottom:0}details.dropdown[open]>summary+ul{transform:scaleY(1);opacity:1;transition:opacity var(--pico-transition),transform 0s ease-in-out 0s}details.dropdown[open]>summary:before{display:block;z-index:1;position:fixed;width:100vw;height:100vh;inset:0;background:none;content:\"\";cursor:default}label>details.dropdown{margin-top:calc(var(--pico-spacing) * .25)}[role=search],[role=group]{display:inline-flex;position:relative;width:100%;margin-bottom:var(--pico-spacing);border-radius:var(--pico-border-radius);box-shadow:var(--pico-group-box-shadow, 0 0 0 rgba(0, 0, 0, 0));vertical-align:middle;transition:box-shadow var(--pico-transition)}[role=search]>*,[role=search] input:not([type=checkbox],[type=radio]),[role=search] select,[role=group]>*,[role=group] input:not([type=checkbox],[type=radio]),[role=group] select{position:relative;flex:1 1 auto;margin-bottom:0}[role=search]>*:not(:first-child),[role=search] input:not([type=checkbox],[type=radio]):not(:first-child),[role=search] select:not(:first-child),[role=group]>*:not(:first-child),[role=group] input:not([type=checkbox],[type=radio]):not(:first-child),[role=group] select:not(:first-child){margin-left:0;border-top-left-radius:0;border-bottom-left-radius:0}[role=search]>*:not(:last-child),[role=search] input:not([type=checkbox],[type=radio]):not(:last-child),[role=search] select:not(:last-child),[role=group]>*:not(:last-child),[role=group] input:not([type=checkbox],[type=radio]):not(:last-child),[role=group] select:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}[role=search]>*:focus,[role=search] input:not([type=checkbox],[type=radio]):focus,[role=search] select:focus,[role=group]>*:focus,[role=group] input:not([type=checkbox],[type=radio]):focus,[role=group] select:focus{z-index:2}[role=search] button:not(:first-child),[role=search] [type=submit]:not(:first-child),[role=search] [type=reset]:not(:first-child),[role=search] [type=button]:not(:first-child),[role=search] [role=button]:not(:first-child),[role=search] input:not([type=checkbox],[type=radio]):not(:first-child),[role=search] select:not(:first-child),[role=group] button:not(:first-child),[role=group] [type=submit]:not(:first-child),[role=group] [type=reset]:not(:first-child),[role=group] [type=button]:not(:first-child),[role=group] [role=button]:not(:first-child),[role=group] input:not([type=checkbox],[type=radio]):not(:first-child),[role=group] select:not(:first-child){margin-left:calc(var(--pico-border-width) * -1)}[role=search] button,[role=search] [type=submit],[role=search] [type=reset],[role=search] [type=button],[role=search] [role=button],[role=group] button,[role=group] [type=submit],[role=group] [type=reset],[role=group] [type=button],[role=group] [role=button]{width:auto}@supports selector(:has(*)){[role=search]:has(button:focus,[type=submit]:focus,[type=button]:focus,[role=button]:focus),[role=group]:has(button:focus,[type=submit]:focus,[type=button]:focus,[role=button]:focus){--pico-group-box-shadow: var(--pico-group-box-shadow-focus-with-button)}[role=search]:has(button:focus,[type=submit]:focus,[type=button]:focus,[role=button]:focus) input:not([type=checkbox],[type=radio]),[role=search]:has(button:focus,[type=submit]:focus,[type=button]:focus,[role=button]:focus) select,[role=group]:has(button:focus,[type=submit]:focus,[type=button]:focus,[role=button]:focus) input:not([type=checkbox],[type=radio]),[role=group]:has(button:focus,[type=submit]:focus,[type=button]:focus,[role=button]:focus) select{border-color:transparent}[role=search]:has(input:not([type=submit],[type=button]):focus,select:focus),[role=group]:has(input:not([type=submit],[type=button]):focus,select:focus){--pico-group-box-shadow: var(--pico-group-box-shadow-focus-with-input)}[role=search]:has(input:not([type=submit],[type=button]):focus,select:focus) button,[role=search]:has(input:not([type=submit],[type=button]):focus,select:focus) [type=submit],[role=search]:has(input:not([type=submit],[type=button]):focus,select:focus) [type=button],[role=search]:has(input:not([type=submit],[type=button]):focus,select:focus) [role=button],[role=group]:has(input:not([type=submit],[type=button]):focus,select:focus) button,[role=group]:has(input:not([type=submit],[type=button]):focus,select:focus) [type=submit],[role=group]:has(input:not([type=submit],[type=button]):focus,select:focus) [type=button],[role=group]:has(input:not([type=submit],[type=button]):focus,select:focus) [role=button]{--pico-button-box-shadow: 0 0 0 var(--pico-border-width) var(--pico-primary-border);--pico-button-hover-box-shadow: 0 0 0 var(--pico-border-width) var(--pico-primary-hover-border)}[role=search] button:focus,[role=search] [type=submit]:focus,[role=search] [type=reset]:focus,[role=search] [type=button]:focus,[role=search] [role=button]:focus,[role=group] button:focus,[role=group] [type=submit]:focus,[role=group] [type=reset]:focus,[role=group] [type=button]:focus,[role=group] [role=button]:focus{box-shadow:none}}[role=search]>*:first-child{border-top-left-radius:5rem;border-bottom-left-radius:5rem}[role=search]>*:last-child{border-top-right-radius:5rem;border-bottom-right-radius:5rem}[aria-busy=true]:not(input,select,textarea,html,form){white-space:nowrap}[aria-busy=true]:not(input,select,textarea,html,form):before{display:inline-block;width:1em;height:1em;background-image:var(--pico-icon-loading);background-size:1em auto;background-repeat:no-repeat;content:\"\";vertical-align:-.125em}[aria-busy=true]:not(input,select,textarea,html,form):not(:empty):before{margin-inline-end:calc(var(--pico-spacing) * .5)}[aria-busy=true]:not(input,select,textarea,html,form):empty{text-align:center}button[aria-busy=true],[type=submit][aria-busy=true],[type=button][aria-busy=true],[type=reset][aria-busy=true],[role=button][aria-busy=true],a[aria-busy=true]{pointer-events:none}:root,:host{--pico-scrollbar-width: 0px}dialog{display:flex;z-index:999;position:fixed;inset:0;align-items:center;justify-content:center;width:inherit;min-width:100%;height:inherit;min-height:100%;padding:0;border:0;-webkit-backdrop-filter:var(--pico-modal-overlay-backdrop-filter);backdrop-filter:var(--pico-modal-overlay-backdrop-filter);background-color:var(--pico-modal-overlay-background-color);color:var(--pico-color)}dialog>article{width:100%;max-height:calc(100vh - var(--pico-spacing) * 2);margin:var(--pico-spacing);overflow:auto}@media (min-width: 576px){dialog>article{max-width:510px}}@media (min-width: 768px){dialog>article{max-width:700px}}dialog>article>header>*{margin-bottom:0}dialog>article>header .close,dialog>article>header :is(a,button)[rel=prev]{margin:0;margin-left:var(--pico-spacing);padding:0;float:right}dialog>article>footer{text-align:right}dialog>article>footer button,dialog>article>footer [role=button]{margin-bottom:0}dialog>article>footer button:not(:first-of-type),dialog>article>footer [role=button]:not(:first-of-type){margin-left:calc(var(--pico-spacing) * .5)}dialog>article .close,dialog>article :is(a,button)[rel=prev]{display:block;width:1rem;height:1rem;margin-top:calc(var(--pico-spacing) * -1);margin-bottom:var(--pico-spacing);margin-left:auto;border:none;background-image:var(--pico-icon-close);background-position:center;background-size:auto 1rem;background-repeat:no-repeat;background-color:transparent;opacity:.5;transition:opacity var(--pico-transition)}dialog>article .close:is([aria-current]:not([aria-current=false]),:hover,:active,:focus),dialog>article :is(a,button)[rel=prev]:is([aria-current]:not([aria-current=false]),:hover,:active,:focus){opacity:1}dialog:not([open]),dialog[open=false]{display:none}.modal-is-open{padding-right:var(--pico-scrollbar-width, 0px);overflow:hidden;pointer-events:none;touch-action:none}.modal-is-open dialog{pointer-events:auto;touch-action:auto}:where(.modal-is-opening,.modal-is-closing) dialog,:where(.modal-is-opening,.modal-is-closing) dialog>article{animation-duration:.2s;animation-timing-function:ease-in-out;animation-fill-mode:both}:where(.modal-is-opening,.modal-is-closing) dialog{animation-duration:.8s;animation-name:modal-overlay}:where(.modal-is-opening,.modal-is-closing) dialog>article{animation-delay:.2s;animation-name:modal}.modal-is-closing dialog,.modal-is-closing dialog>article{animation-delay:0s;animation-direction:reverse}@keyframes modal-overlay{0%{-webkit-backdrop-filter:none;backdrop-filter:none;background-color:transparent}}@keyframes modal{0%{transform:translateY(-100%);opacity:0}}:where(nav li):before{float:left;content:\"\\200b\"}nav,nav ul{display:flex}nav{justify-content:space-between;overflow:visible}nav ol,nav ul{align-items:center;margin-bottom:0;padding:0;list-style:none}nav ol:first-of-type,nav ul:first-of-type{margin-left:calc(var(--pico-nav-element-spacing-horizontal) * -1)}nav ol:last-of-type,nav ul:last-of-type{margin-right:calc(var(--pico-nav-element-spacing-horizontal) * -1)}nav li{display:inline-block;margin:0;padding:var(--pico-nav-element-spacing-vertical) var(--pico-nav-element-spacing-horizontal)}nav li :where(a,[role=link]){display:inline-block;margin:calc(var(--pico-nav-link-spacing-vertical) * -1) calc(var(--pico-nav-link-spacing-horizontal) * -1);padding:var(--pico-nav-link-spacing-vertical) var(--pico-nav-link-spacing-horizontal);border-radius:var(--pico-border-radius)}nav li :where(a,[role=link]):not(:hover){text-decoration:none}nav li button,nav li [role=button],nav li [type=button],nav li input:not([type=checkbox],[type=radio],[type=range],[type=file]),nav li select{height:auto;margin-right:inherit;margin-bottom:0;margin-left:inherit;padding:calc(var(--pico-nav-link-spacing-vertical) - var(--pico-border-width) * 2) var(--pico-nav-link-spacing-horizontal)}nav[aria-label=breadcrumb]{align-items:center;justify-content:start}nav[aria-label=breadcrumb] ul li:not(:first-child){margin-inline-start:var(--pico-nav-link-spacing-horizontal)}nav[aria-label=breadcrumb] ul li a{margin:calc(var(--pico-nav-link-spacing-vertical) * -1) 0;margin-inline-start:calc(var(--pico-nav-link-spacing-horizontal) * -1)}nav[aria-label=breadcrumb] ul li:not(:last-child):after{display:inline-block;position:absolute;width:calc(var(--pico-nav-link-spacing-horizontal) * 4);margin:0 calc(var(--pico-nav-link-spacing-horizontal) * -1);content:var(--pico-nav-breadcrumb-divider);color:var(--pico-muted-color);text-align:center;text-decoration:none;white-space:nowrap}nav[aria-label=breadcrumb] a[aria-current]:not([aria-current=false]){background-color:transparent;color:inherit;text-decoration:none;pointer-events:none}aside nav,aside ol,aside ul,aside li{display:block}aside li{padding:calc(var(--pico-nav-element-spacing-vertical) * .5) var(--pico-nav-element-spacing-horizontal)}aside li a{display:block}aside li [role=button]{margin:inherit}[dir=rtl] nav[aria-label=breadcrumb] ul li:not(:last-child) :after{content:\"\\\\\"}progress{display:inline-block;vertical-align:baseline}progress{-webkit-appearance:none;-moz-appearance:none;display:inline-block;appearance:none;width:100%;height:.5rem;margin-bottom:calc(var(--pico-spacing) * .5);overflow:hidden;border:0;border-radius:var(--pico-border-radius);background-color:var(--pico-progress-background-color);color:var(--pico-progress-color)}progress::-webkit-progress-bar{border-radius:var(--pico-border-radius);background:none}progress[value]::-webkit-progress-value{background-color:var(--pico-progress-color);transition:inline-size var(--pico-transition)}progress::-moz-progress-bar{background-color:var(--pico-progress-color)}@media (prefers-reduced-motion: no-preference){progress:indeterminate{background:var(--pico-progress-background-color) linear-gradient(to right,var(--pico-progress-color) 30%,var(--pico-progress-background-color) 30%) top left/150% 150% no-repeat;animation:progress-indeterminate 1s linear infinite}progress:indeterminate[value]::-webkit-progress-value{background-color:transparent}progress:indeterminate::-moz-progress-bar{background-color:transparent}}@media (prefers-reduced-motion: no-preference){[dir=rtl] progress:indeterminate{animation-direction:reverse}}@keyframes progress-indeterminate{0%{background-position:200% 0}to{background-position:-200% 0}}[data-tooltip]{position:relative}[data-tooltip]:not(a,button,input,[role=button]){border-bottom:1px dotted;text-decoration:none;cursor:help}[data-tooltip][data-placement=top]:before,[data-tooltip][data-placement=top]:after,[data-tooltip]:before,[data-tooltip]:after{display:block;z-index:99;position:absolute;bottom:100%;left:50%;padding:.25rem .5rem;overflow:hidden;transform:translate(-50%,-.25rem);border-radius:var(--pico-border-radius);background:var(--pico-tooltip-background-color);content:attr(data-tooltip);color:var(--pico-tooltip-color);font-style:normal;font-weight:var(--pico-font-weight);font-size:.875rem;text-decoration:none;text-overflow:ellipsis;white-space:nowrap;opacity:0;pointer-events:none}[data-tooltip][data-placement=top]:after,[data-tooltip]:after{padding:0;transform:translate(-50%);border-top:.3rem solid;border-right:.3rem solid transparent;border-left:.3rem solid transparent;border-radius:0;background-color:transparent;content:\"\";color:var(--pico-tooltip-background-color)}[data-tooltip][data-placement=bottom]:before,[data-tooltip][data-placement=bottom]:after{top:100%;bottom:auto;transform:translate(-50%,.25rem)}[data-tooltip][data-placement=bottom]:after{transform:translate(-50%,-.3rem);border:.3rem solid transparent;border-bottom:.3rem solid}[data-tooltip][data-placement=left]:before,[data-tooltip][data-placement=left]:after{inset:50% 100% auto auto;transform:translate(-.25rem,-50%)}[data-tooltip][data-placement=left]:after{transform:translate(.3rem,-50%);border:.3rem solid transparent;border-left:.3rem solid}[data-tooltip][data-placement=right]:before,[data-tooltip][data-placement=right]:after{inset:50% auto auto 100%;transform:translate(.25rem,-50%)}[data-tooltip][data-placement=right]:after{transform:translate(-.3rem,-50%);border:.3rem solid transparent;border-right:.3rem solid}[data-tooltip]:focus:before,[data-tooltip]:focus:after,[data-tooltip]:hover:before,[data-tooltip]:hover:after{opacity:1}@media (hover: hover) and (pointer: fine){[data-tooltip]:focus:before,[data-tooltip]:focus:after,[data-tooltip]:hover:before,[data-tooltip]:hover:after{--pico-tooltip-slide-to: translate(-50%, -.25rem);transform:translate(-50%,.75rem);animation-duration:.2s;animation-fill-mode:forwards;animation-name:tooltip-slide;opacity:0}[data-tooltip]:focus:after,[data-tooltip]:hover:after{--pico-tooltip-caret-slide-to: translate(-50%, 0rem);transform:translate(-50%,-.25rem);animation-name:tooltip-caret-slide}[data-tooltip][data-placement=bottom]:focus:before,[data-tooltip][data-placement=bottom]:focus:after,[data-tooltip][data-placement=bottom]:hover:before,[data-tooltip][data-placement=bottom]:hover:after{--pico-tooltip-slide-to: translate(-50%, .25rem);transform:translate(-50%,-.75rem);animation-name:tooltip-slide}[data-tooltip][data-placement=bottom]:focus:after,[data-tooltip][data-placement=bottom]:hover:after{--pico-tooltip-caret-slide-to: translate(-50%, -.3rem);transform:translate(-50%,-.5rem);animation-name:tooltip-caret-slide}[data-tooltip][data-placement=left]:focus:before,[data-tooltip][data-placement=left]:focus:after,[data-tooltip][data-placement=left]:hover:before,[data-tooltip][data-placement=left]:hover:after{--pico-tooltip-slide-to: translate(-.25rem, -50%);transform:translate(.75rem,-50%);animation-name:tooltip-slide}[data-tooltip][data-placement=left]:focus:after,[data-tooltip][data-placement=left]:hover:after{--pico-tooltip-caret-slide-to: translate(.3rem, -50%);transform:translate(.05rem,-50%);animation-name:tooltip-caret-slide}[data-tooltip][data-placement=right]:focus:before,[data-tooltip][data-placement=right]:focus:after,[data-tooltip][data-placement=right]:hover:before,[data-tooltip][data-placement=right]:hover:after{--pico-tooltip-slide-to: translate(.25rem, -50%);transform:translate(-.75rem,-50%);animation-name:tooltip-slide}[data-tooltip][data-placement=right]:focus:after,[data-tooltip][data-placement=right]:hover:after{--pico-tooltip-caret-slide-to: translate(-.3rem, -50%);transform:translate(-.05rem,-50%);animation-name:tooltip-caret-slide}}@keyframes tooltip-slide{to{transform:var(--pico-tooltip-slide-to);opacity:1}}@keyframes tooltip-caret-slide{50%{opacity:0}to{transform:var(--pico-tooltip-caret-slide-to);opacity:1}}[aria-controls]{cursor:pointer}[aria-disabled=true],[disabled]{cursor:not-allowed}[aria-hidden=false][hidden]{display:initial}[aria-hidden=false][hidden]:not(:focus){clip:rect(0,0,0,0);position:absolute}a,area,button,input,label,select,summary,textarea,[tabindex]{-ms-touch-action:manipulation}[dir=rtl]{direction:rtl}@media (prefers-reduced-motion: reduce){*:not([aria-busy=true]),:not([aria-busy=true]):before,:not([aria-busy=true]):after{background-attachment:initial!important;animation-duration:1ms!important;animation-delay:-1ms!important;animation-iteration-count:1!important;scroll-behavior:auto!important;transition-delay:0s!important;transition-duration:0s!important}}:host{display:block;background-color:var(--pico-background-color);height:100%;width:100%}fieldset legend{font-weight:700}.toolbar-container{padding:4px;height:100%;display:flex;justify-content:center}.toolbar-container .button-container{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px}.toolbar-container .buttons-divider{border-top:1px solid var(--pico-secondary);margin:1rem 0;width:100%}.toolbar-container.horizontal{width:100%}.toolbar-container.horizontal .button-container{flex-direction:row}.toolbar-container.horizontal .buttons-divider{border-left:1px solid var(--pico-secondary);height:100%;margin:0 1rem;width:0}.toolbar-position-buttons{display:flex;gap:4px}.toolbar-position-buttons button{flex-grow:1}.power-buttons button{display:block;width:100%}.settings-toolbar-dock{margin-top:1rem}\n/*!\n * Pico CSS \u2728 v2.1.1 (https://picocss.com)\n * Copyright 2019-2025 - Licensed under MIT\n */\n"], dependencies: [{ kind: "component", type: ConsoleToolbarDefaultButtonComponent, selector: "cf-console-toolbar-default-button", inputs: ["disabled", "label", "isOngoing"], outputs: ["clicked"] }], encapsulation: i0.ViewEncapsulation.ShadowDom });
|
|
254
|
+
}
|
|
255
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConsoleToolbarDefaultComponent, decorators: [{
|
|
256
|
+
type: Component,
|
|
257
|
+
args: [{ selector: 'cf-console-toolbar-default', imports: [ConsoleToolbarDefaultButtonComponent], standalone: true, encapsulation: ViewEncapsulation.ShadowDom, template: "<!-- ===BEGIN LICENSE=== -->\n<!-- Copyright 2025 Carnegie Mellon University. All rights reserved. -->\n<!-- Released under an MIT (SEI)-style license. See the LICENSE.md file for license information. -->\n<!-- ===END LICENSE=== -->\n\n@if (consoleContext()) {\n<div class=\"toolbar-container\"\n [class.horizontal]=\"consoleContext().userSettings.settings().toolbar.dockTo == 'top' || consoleContext().userSettings.settings().toolbar.dockTo == 'bottom' \">\n <div class=\"button-container\">\n <cf-console-toolbar-default-button label=\"Settings\" (clicked)=\"handleSettingsDialogOpenClose(true)\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M12 8.25C9.92894 8.25 8.25 9.92893 8.25 12C8.25 14.0711 9.92894 15.75 12 15.75C14.0711 15.75 15.75 14.0711 15.75 12C15.75 9.92893 14.0711 8.25 12 8.25ZM9.75 12C9.75 10.7574 10.7574 9.75 12 9.75C13.2426 9.75 14.25 10.7574 14.25 12C14.25 13.2426 13.2426 14.25 12 14.25C10.7574 14.25 9.75 13.2426 9.75 12Z\"\n fill=\"#1C274C\"></path>\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M11.9747 1.25C11.5303 1.24999 11.1592 1.24999 10.8546 1.27077C10.5375 1.29241 10.238 1.33905 9.94761 1.45933C9.27379 1.73844 8.73843 2.27379 8.45932 2.94762C8.31402 3.29842 8.27467 3.66812 8.25964 4.06996C8.24756 4.39299 8.08454 4.66251 7.84395 4.80141C7.60337 4.94031 7.28845 4.94673 7.00266 4.79568C6.64714 4.60777 6.30729 4.45699 5.93083 4.40743C5.20773 4.31223 4.47642 4.50819 3.89779 4.95219C3.64843 5.14353 3.45827 5.3796 3.28099 5.6434C3.11068 5.89681 2.92517 6.21815 2.70294 6.60307L2.67769 6.64681C2.45545 7.03172 2.26993 7.35304 2.13562 7.62723C1.99581 7.91267 1.88644 8.19539 1.84541 8.50701C1.75021 9.23012 1.94617 9.96142 2.39016 10.5401C2.62128 10.8412 2.92173 11.0602 3.26217 11.2741C3.53595 11.4461 3.68788 11.7221 3.68786 12C3.68785 12.2778 3.53592 12.5538 3.26217 12.7258C2.92169 12.9397 2.62121 13.1587 2.39007 13.4599C1.94607 14.0385 1.75012 14.7698 1.84531 15.4929C1.88634 15.8045 1.99571 16.0873 2.13552 16.3727C2.26983 16.6469 2.45535 16.9682 2.67758 17.3531L2.70284 17.3969C2.92507 17.7818 3.11058 18.1031 3.28089 18.3565C3.45817 18.6203 3.64833 18.8564 3.89769 19.0477C4.47632 19.4917 5.20763 19.6877 5.93073 19.5925C6.30717 19.5429 6.647 19.3922 7.0025 19.2043C7.28833 19.0532 7.60329 19.0596 7.8439 19.1986C8.08452 19.3375 8.24756 19.607 8.25964 19.9301C8.27467 20.3319 8.31403 20.7016 8.45932 21.0524C8.73843 21.7262 9.27379 22.2616 9.94761 22.5407C10.238 22.661 10.5375 22.7076 10.8546 22.7292C11.1592 22.75 11.5303 22.75 11.9747 22.75H12.0252C12.4697 22.75 12.8407 22.75 13.1454 22.7292C13.4625 22.7076 13.762 22.661 14.0524 22.5407C14.7262 22.2616 15.2616 21.7262 15.5407 21.0524C15.686 20.7016 15.7253 20.3319 15.7403 19.93C15.7524 19.607 15.9154 19.3375 16.156 19.1985C16.3966 19.0596 16.7116 19.0532 16.9974 19.2042C17.3529 19.3921 17.6927 19.5429 18.0692 19.5924C18.7923 19.6876 19.5236 19.4917 20.1022 19.0477C20.3516 18.8563 20.5417 18.6203 20.719 18.3565C20.8893 18.1031 21.0748 17.7818 21.297 17.3969L21.3223 17.3531C21.5445 16.9682 21.7301 16.6468 21.8644 16.3726C22.0042 16.0872 22.1135 15.8045 22.1546 15.4929C22.2498 14.7697 22.0538 14.0384 21.6098 13.4598C21.3787 13.1586 21.0782 12.9397 20.7378 12.7258C20.464 12.5538 20.3121 12.2778 20.3121 11.9999C20.3121 11.7221 20.464 11.4462 20.7377 11.2742C21.0783 11.0603 21.3788 10.8414 21.6099 10.5401C22.0539 9.96149 22.2499 9.23019 22.1547 8.50708C22.1136 8.19546 22.0043 7.91274 21.8645 7.6273C21.7302 7.35313 21.5447 7.03183 21.3224 6.64695L21.2972 6.60318C21.0749 6.21825 20.8894 5.89688 20.7191 5.64347C20.5418 5.37967 20.3517 5.1436 20.1023 4.95225C19.5237 4.50826 18.7924 4.3123 18.0692 4.4075C17.6928 4.45706 17.353 4.60782 16.9975 4.79572C16.7117 4.94679 16.3967 4.94036 16.1561 4.80144C15.9155 4.66253 15.7524 4.39297 15.7403 4.06991C15.7253 3.66808 15.686 3.2984 15.5407 2.94762C15.2616 2.27379 14.7262 1.73844 14.0524 1.45933C13.762 1.33905 13.4625 1.29241 13.1454 1.27077C12.8407 1.24999 12.4697 1.24999 12.0252 1.25H11.9747ZM10.5216 2.84515C10.5988 2.81319 10.716 2.78372 10.9567 2.76729C11.2042 2.75041 11.5238 2.75 12 2.75C12.4762 2.75 12.7958 2.75041 13.0432 2.76729C13.284 2.78372 13.4012 2.81319 13.4783 2.84515C13.7846 2.97202 14.028 3.21536 14.1548 3.52165C14.1949 3.61826 14.228 3.76887 14.2414 4.12597C14.271 4.91835 14.68 5.68129 15.4061 6.10048C16.1321 6.51968 16.9974 6.4924 17.6984 6.12188C18.0143 5.9549 18.1614 5.90832 18.265 5.89467C18.5937 5.8514 18.9261 5.94047 19.1891 6.14228C19.2554 6.19312 19.3395 6.27989 19.4741 6.48016C19.6125 6.68603 19.7726 6.9626 20.0107 7.375C20.2488 7.78741 20.4083 8.06438 20.5174 8.28713C20.6235 8.50382 20.6566 8.62007 20.6675 8.70287C20.7108 9.03155 20.6217 9.36397 20.4199 9.62698C20.3562 9.70995 20.2424 9.81399 19.9397 10.0041C19.2684 10.426 18.8122 11.1616 18.8121 11.9999C18.8121 12.8383 19.2683 13.574 19.9397 13.9959C20.2423 14.186 20.3561 14.29 20.4198 14.373C20.6216 14.636 20.7107 14.9684 20.6674 15.2971C20.6565 15.3799 20.6234 15.4961 20.5173 15.7128C20.4082 15.9355 20.2487 16.2125 20.0106 16.6249C19.7725 17.0373 19.6124 17.3139 19.474 17.5198C19.3394 17.72 19.2553 17.8068 19.189 17.8576C18.926 18.0595 18.5936 18.1485 18.2649 18.1053C18.1613 18.0916 18.0142 18.045 17.6983 17.8781C16.9973 17.5075 16.132 17.4803 15.4059 17.8995C14.68 18.3187 14.271 19.0816 14.2414 19.874C14.228 20.2311 14.1949 20.3817 14.1548 20.4784C14.028 20.7846 13.7846 21.028 13.4783 21.1549C13.4012 21.1868 13.284 21.2163 13.0432 21.2327C12.7958 21.2496 12.4762 21.25 12 21.25C11.5238 21.25 11.2042 21.2496 10.9567 21.2327C10.716 21.2163 10.5988 21.1868 10.5216 21.1549C10.2154 21.028 9.97201 20.7846 9.84514 20.4784C9.80512 20.3817 9.77195 20.2311 9.75859 19.874C9.72896 19.0817 9.31997 18.3187 8.5939 17.8995C7.86784 17.4803 7.00262 17.5076 6.30158 17.8781C5.98565 18.0451 5.83863 18.0917 5.73495 18.1053C5.40626 18.1486 5.07385 18.0595 4.81084 17.8577C4.74458 17.8069 4.66045 17.7201 4.52586 17.5198C4.38751 17.314 4.22736 17.0374 3.98926 16.625C3.75115 16.2126 3.59171 15.9356 3.4826 15.7129C3.37646 15.4962 3.34338 15.3799 3.33248 15.2971C3.28921 14.9684 3.37828 14.636 3.5801 14.373C3.64376 14.2901 3.75761 14.186 4.0602 13.9959C4.73158 13.5741 5.18782 12.8384 5.18786 12.0001C5.18791 11.1616 4.73165 10.4259 4.06021 10.004C3.75769 9.81389 3.64385 9.70987 3.58019 9.62691C3.37838 9.3639 3.28931 9.03149 3.33258 8.7028C3.34348 8.62001 3.37656 8.50375 3.4827 8.28707C3.59181 8.06431 3.75125 7.78734 3.98935 7.37493C4.22746 6.96253 4.3876 6.68596 4.52596 6.48009C4.66055 6.27983 4.74468 6.19305 4.81093 6.14222C5.07395 5.9404 5.40636 5.85133 5.73504 5.8946C5.83873 5.90825 5.98576 5.95483 6.30173 6.12184C7.00273 6.49235 7.86791 6.51962 8.59394 6.10045C9.31998 5.68128 9.72896 4.91837 9.75859 4.12602C9.77195 3.76889 9.80512 3.61827 9.84514 3.52165C9.97201 3.21536 10.2154 2.97202 10.5216 2.84515Z\"\n fill=\"#1C274C\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n\n <div class=\"buttons-divider\"></div>\n\n @if(cfConfig.enableClipboard) {\n <cf-console-toolbar-default-button [disabled]=\"!consoleContext().state.isConnected()\" label=\"Clipboard\"\n (clicked)=\"handleClipboardDialogOpenClose(true)\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M8 5.00005C7.01165 5.00082 6.49359 5.01338 6.09202 5.21799C5.71569 5.40973 5.40973 5.71569 5.21799 6.09202C5 6.51984 5 7.07989 5 8.2V17.8C5 18.9201 5 19.4802 5.21799 19.908C5.40973 20.2843 5.71569 20.5903 6.09202 20.782C6.51984 21 7.07989 21 8.2 21H15.8C16.9201 21 17.4802 21 17.908 20.782C18.2843 20.5903 18.5903 20.2843 18.782 19.908C19 19.4802 19 18.9201 19 17.8V8.2C19 7.07989 19 6.51984 18.782 6.09202C18.5903 5.71569 18.2843 5.40973 17.908 5.21799C17.5064 5.01338 16.9884 5.00082 16 5.00005M8 5.00005V7H16V5.00005M8 5.00005V4.70711C8 4.25435 8.17986 3.82014 8.5 3.5C8.82014 3.17986 9.25435 3 9.70711 3H14.2929C14.7456 3 15.1799 3.17986 15.5 3.5C15.8201 3.82014 16 4.25435 16 4.70711V5.00005\"\n stroke=\"#000000\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n }\n\n <cf-console-toolbar-default-button (clicked)=\"consoleContext().console.copyScreenshot()\"\n [disabled]=\"!consoleContext().state.isConnected()\" label=\"Screenshot\">\n <svg width=\"800px\" height=\"800px\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M9.15023 3.01742C9.13605 3.03985 9.12278 3.0676 9.11298 3.09958C9.11044 3.10789 9.10778 3.11617 9.10502 3.12442L8.36963 5.31787C8.23301 5.72537 7.85129 6 7.4215 6H3C2.44772 6 2 6.44772 2 7V20C2 20.5523 2.44771 21 3 21H21C21.5523 21 22 20.5523 22 20V7C22 6.44771 21.5523 6 21 6H16.331C15.9011 6 15.5194 5.72528 15.3828 5.31769L14.6479 3.12423C14.6452 3.11605 14.6425 3.10783 14.64 3.09958C14.6302 3.0676 14.6169 3.03985 14.6027 3.01742C14.5986 3.01089 14.5946 3.00509 14.5908 3H9.16221C9.1584 3.00509 9.15437 3.01089 9.15023 3.01742ZM7.20525 2.49911C7.43535 1.76672 8.10563 1 9.06392 1H14.6891C15.6474 1 16.3177 1.76679 16.5478 2.49922L17.0506 4H21C22.6569 4 24 5.34315 24 7V20C24 21.6569 22.6569 23 21 23H3C1.34315 23 0 21.6569 0 20V7C0 5.34315 1.34315 4 3 4H6.70206L7.20525 2.49911ZM7 13C7 10.2386 9.23858 8 12 8C14.7614 8 17 10.2386 17 13C17 15.7614 14.7614 18 12 18C9.23858 18 7 15.7614 7 13ZM12 10C10.3431 10 9 11.3431 9 13C9 14.6569 10.3431 16 12 16C13.6569 16 15 14.6569 15 13C15 11.3431 13.6569 10 12 10Z\"\n fill=\"none\" />\n </svg>\n </cf-console-toolbar-default-button>\n\n @if (cfConfig.enableConsoleRecord) {\n <cf-console-toolbar-default-button (clicked)=\"handleRecordToggle()\"\n [disabled]=\"!consoleContext().state.isRecordingAvailable()\"\n [isOngoing]=\"!!consoleContext().state.activeConsoleRecording()\" label=\"Record\">\n @if (!consoleContext().state.activeConsoleRecording()) {\n <svg viewBox=\"0 0 20 20\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\" fill=\"#000000\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <title>record [#979]</title>\n <desc>Created with Sketch.</desc>\n <defs> </defs>\n <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n <g id=\"Dribbble-Light-Preview\" transform=\"translate(-100.000000, -3879.000000)\" fill=\"#000000\">\n <g id=\"icons\" transform=\"translate(56.000000, 160.000000)\">\n <path\n d=\"M56,3719 L56,3721 L62,3721 L62,3727 L64,3727 L64,3719 L56,3719 Z M58,3729.151 C58,3726.942 56.209,3725.151 54,3725.151 C51.791,3725.151 50,3726.942 50,3729.151 C50,3731.36 51.791,3733.151 54,3733.151 C56.209,3733.151 58,3731.36 58,3729.151 L58,3729.151 Z M62,3737 L56,3737 L56,3739 L64,3739 L64,3731 L62,3731 L62,3737 Z M46,3731 L44,3731 L44,3739 L52,3739 L52,3737 L46,3737 L46,3731 Z M46,3727 L44,3727 L44,3719 L52,3719 L52,3721 L46,3721 L46,3727 Z\"\n id=\"record-[#979]\"> </path>\n </g>\n </g>\n </g>\n </g>\n </svg>\n } @else {\n <svg viewBox=\"0 -0.5 21 21\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\" fill=\"#000000\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n <g id=\"Dribbble-Light-Preview\" transform=\"translate(-59.000000, -440.000000)\" fill=\"#000000\">\n <g id=\"icons\" transform=\"translate(56.000000, 160.000000)\">\n <path\n d=\"M9.3,294 L17.7,294 L17.7,286 L9.3,286 L9.3,294 Z M15.6,280 L15.6,282 L21.9,282 L21.9,288 L24,288 L24,280 L15.6,280 Z M21.9,298 L15.6,298 L15.6,300 L24,300 L24,292 L21.9,292 L21.9,298 Z M5.1,292 L3,292 L3,300 L11.4,300 L11.4,298 L5.1,298 L5.1,292 Z M5.1,288 L3,288 L3,280 L11.4,280 L11.4,282 L5.1,282 L5.1,288 Z\"\n id=\"stop-[#1470]\"> </path>\n </g>\n </g>\n </g>\n </g>\n </svg>\n }\n </cf-console-toolbar-default-button>\n }\n\n <cf-console-toolbar-default-button (clicked)=\"consoleContext().console.toggleFullscreen()\" label=\"Fullscreen\">\n @if (consoleContext().state.isFullscreenAvailable()) {\n <svg width=\"800px\" height=\"800px\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M21.7092 2.29502C21.8041 2.3904 21.8757 2.50014 21.9241 2.61722C21.9727 2.73425 21.9996 2.8625 22 2.997L22 3V9C22 9.55228 21.5523 10 21 10C20.4477 10 20 9.55228 20 9V5.41421L14.7071 10.7071C14.3166 11.0976 13.6834 11.0976 13.2929 10.7071C12.9024 10.3166 12.9024 9.68342 13.2929 9.29289L18.5858 4H15C14.4477 4 14 3.55228 14 3C14 2.44772 14.4477 2 15 2H20.9998C21.2749 2 21.5242 2.11106 21.705 2.29078L21.7092 2.29502Z\"\n fill=\"#000000\" />\n <path\n d=\"M10.7071 14.7071L5.41421 20H9C9.55228 20 10 20.4477 10 21C10 21.5523 9.55228 22 9 22H3.00069L2.997 22C2.74301 21.9992 2.48924 21.9023 2.29502 21.7092L2.29078 21.705C2.19595 21.6096 2.12432 21.4999 2.07588 21.3828C2.02699 21.2649 2 21.1356 2 21V15C2 14.4477 2.44772 14 3 14C3.55228 14 4 14.4477 4 15V18.5858L9.29289 13.2929C9.68342 12.9024 10.3166 12.9024 10.7071 13.2929C11.0976 13.6834 11.0976 14.3166 10.7071 14.7071Z\"\n fill=\"#000000\" />\n </svg>\n } @else {\n <svg width=\"800px\" height=\"800px\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M7 9C8.10457 9 9 8.10457 9 7V3C9 2.44772 8.55228 2 8 2C7.44772 2 7 2.44772 7 3V7H3C2.44772 7 2 7.44772 2 8C2 8.55228 2.44772 9 3 9H7Z\"\n fill=\"#000000\" />\n <path\n d=\"M17 9C15.8954 9 15 8.10457 15 7V3C15 2.44772 15.4477 2 16 2C16.5523 2 17 2.44772 17 3V7H21C21.5523 7 22 7.44772 22 8C22 8.55228 21.5523 9 21 9H17Z\"\n fill=\"#000000\" />\n <path\n d=\"M17 15C15.8954 15 15 15.8954 15 17V21C15 21.5523 15.4477 22 16 22C16.5523 22 17 21.5523 17 21V17H21C21.5523 17 22 16.5523 22 16C22 15.4477 21.5523 15 21 15H17Z\"\n fill=\"#000000\" />\n <path\n d=\"M9 17C9 15.8954 8.10457 15 7 15H3C2.44772 15 2 15.4477 2 16C2 16.5523 2.44772 17 3 17H7V21C7 21.5523 7.44772 22 8 22C8.55228 22 9 21.5523 9 21V17Z\"\n fill=\"#000000\" />\n </svg>\n }\n </cf-console-toolbar-default-button>\n\n @if (consoleContext().networks.config()?.available?.length && consoleContext().state.isConnected()) {\n <div class=\"buttons-divider\"></div>\n\n <cf-console-toolbar-default-button\n label=\"Networks ({{ consoleContext().networks.config()?.available?.length }})\"\n (clicked)=\"handleNetworkDialogOpenClose(true)\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path\n d=\"M3 12H21M12 8V12M6.5 12V16M17.5 12V16M10.1 8H13.9C14.4601 8 14.7401 8 14.954 7.89101C15.1422 7.79513 15.2951 7.64215 15.391 7.45399C15.5 7.24008 15.5 6.96005 15.5 6.4V4.6C15.5 4.03995 15.5 3.75992 15.391 3.54601C15.2951 3.35785 15.1422 3.20487 14.954 3.10899C14.7401 3 14.4601 3 13.9 3H10.1C9.53995 3 9.25992 3 9.04601 3.10899C8.85785 3.20487 8.70487 3.35785 8.60899 3.54601C8.5 3.75992 8.5 4.03995 8.5 4.6V6.4C8.5 6.96005 8.5 7.24008 8.60899 7.45399C8.70487 7.64215 8.85785 7.79513 9.04601 7.89101C9.25992 8 9.53995 8 10.1 8ZM15.6 21H19.4C19.9601 21 20.2401 21 20.454 20.891C20.6422 20.7951 20.7951 20.6422 20.891 20.454C21 20.2401 21 19.9601 21 19.4V17.6C21 17.0399 21 16.7599 20.891 16.546C20.7951 16.3578 20.6422 16.2049 20.454 16.109C20.2401 16 19.9601 16 19.4 16H15.6C15.0399 16 14.7599 16 14.546 16.109C14.3578 16.2049 14.2049 16.3578 14.109 16.546C14 16.7599 14 17.0399 14 17.6V19.4C14 19.9601 14 20.2401 14.109 20.454C14.2049 20.6422 14.3578 20.7951 14.546 20.891C14.7599 21 15.0399 21 15.6 21ZM4.6 21H8.4C8.96005 21 9.24008 21 9.45399 20.891C9.64215 20.7951 9.79513 20.6422 9.89101 20.454C10 20.2401 10 19.9601 10 19.4V17.6C10 17.0399 10 16.7599 9.89101 16.546C9.79513 16.3578 9.64215 16.2049 9.45399 16.109C9.24008 16 8.96005 16 8.4 16H4.6C4.03995 16 3.75992 16 3.54601 16.109C3.35785 16.2049 3.20487 16.3578 3.10899 16.546C3 16.7599 3 17.0399 3 17.6V19.4C3 19.9601 3 20.2401 3.10899 20.454C3.20487 20.6422 3.35785 20.7951 3.54601 20.891C3.75992 21 4.03995 21 4.6 21Z\"\n stroke=\"#000000\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n }\n\n @if (consoleContext().state.isConnected()) {\n <div class=\"buttons-divider\"></div>\n\n <cf-console-toolbar-default-button label=\"Ctrl+Alt+Del\" (clicked)=\"consoleContext().console.sendCtrlAltDel()\"\n [disabled]=\"!consoleContext().state.isConnected()\">\n <svg fill=\"#000000\" version=\"1.1\" id=\"Layer_1\" xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 8 8\" enable-background=\"new 0 0 8 8\"\n xml:space=\"preserve\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <rect x=\"2.989\" width=\"2.023\" height=\"5.471\"></rect>\n <rect x=\"2.989\" y=\"6.39\" width=\"2.023\" height=\"1.61\"></rect>\n </g>\n </svg>\n </cf-console-toolbar-default-button>\n\n @if (consoleContext().console.supportedFeatures().powerManagement) {\n <cf-console-toolbar-default-button label=\"Power\" (clicked)=\"isPowerDialogOpen = true\">\n <svg width=\"800px\" height=\"800px\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M13 3C13 2.44772 12.5523 2 12 2C11.4477 2 11 2.44772 11 3V13C11 13.5523 11.4477 14 12 14C12.5523 14 13 13.5523 13 13V3Z\"\n fill=\"none\" />\n <path\n d=\"M6.2798 6.70707C6.67031 6.31653 6.67028 5.68337 6.27973 5.29286C5.88919 4.90235 5.25603 4.90238 4.86552 5.29293C3.09635 7.06226 2 9.49298 2 12.1764C2 17.6204 6.49591 22 12 22C17.5041 22 22 17.6204 22 12.1764C22 9.49298 20.9036 7.06226 19.1345 5.29293C18.744 4.90238 18.1108 4.90235 17.7203 5.29286C17.3297 5.68337 17.3297 6.31653 17.7202 6.70707C19.1338 8.12083 20 10.0503 20 12.1764C20 16.4787 16.437 20 12 20C7.56296 20 4 16.4787 4 12.1764C4 10.0503 4.86618 8.12083 6.2798 6.70707Z\"\n fill=\"none\" />\n </svg>\n </cf-console-toolbar-default-button>\n }\n }\n </div>\n</div>\n}\n\n<dialog [open]=\"isClipboardDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"handleClipboardDialogOpenClose(false)\"></button>\n <p>\n <strong>Send Text to Console Clipboard</strong>\n </p>\n </header>\n\n <div>\n <h2>Send Text to Console</h2>\n <form (submit)=\"handleSendClipboardText($event, clipboardText.value)\">\n <fieldset role=\"group\">\n <input type=\"text\" class=\"clipboard-text\" aria-label=\"Clipboard text\"\n placeholder=\"Enter text to send to the console's clipboard\" #clipboardText autofocus>\n <button type=\"submit\"\n [disabled]=\"!clipboardText.value || !consoleContext().state.isConnected\">Send</button>\n </fieldset>\n </form>\n </div>\n\n @if(!userSettings().console.allowCopyToLocalClipboard) {\n <div>\n <h2>Console Clipboard</h2>\n <form (submit)=\"handleClipboardCopyLastText(consoleLastClipboardText.value)\">\n <fieldset role=\"group\">\n <input type=\"text\" class=\"clipboard-text\" aria-label=\"Clipboard text\"\n placeholder=\"Enter text to send to the console's clipboard\" #consoleLastClipboardText autofocus>\n <button type=\"submit\" [disabled]=\"!consoleLastClipboardText.value\">Copy</button>\n </fieldset>\n </form>\n </div>\n }\n </article>\n</dialog>\n\n<dialog [open]=\"isNetworkDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"handleNetworkDialogOpenClose(false)\"></button>\n <p>\n <strong>Select Active Network</strong>\n </p>\n </header>\n\n <form>\n <fieldset role=\"group\">\n <select #availableNetworksSelect name=\"current-network\" aria-label=\"Select a network to connect to\"\n required>\n <option selected value=\"\">\n [Disconnect from network]\n </option>\n\n @for(network of consoleContext().networks.config()?.available; track network) {\n <option [value]=\"network\" [selected]=\"network === consoleContext().networks.config()?.current\">\n {{ network }}\n </option>\n }\n </select>\n\n <button type=\"button\" (click)=\"handleNetworkChangeRequested(availableNetworksSelect.value)\">\n {{ availableNetworksSelect.value ? \"Connect\" : \"Disconnect\" }}\n </button>\n </fieldset>\n </form>\n </article>\n</dialog>\n\n\n<dialog [open]=\"isPowerDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"isPowerDialogOpen = false\"></button>\n <p>\n <strong>Console Power</strong>\n </p>\n </header>\n\n <div class=\"power-buttons\">\n <button type=\"button\" (click)=\"handleSendPowerRequest('reboot')\">Request Reboot</button>\n <button type=\"button\" (click)=\"handleSendPowerRequest('shutdown')\">Request Shutdown</button>\n <hr />\n <button class=\"secondary\" type=\"button\" (click)=\"handleSendPowerRequest('rebootHard')\">\n Request Hard Reboot\n </button>\n </div>\n </article>\n</dialog>\n\n<dialog [open]=\"isSettingsDialogOpen\">\n <article>\n <header>\n <button aria-label=\"Close\" rel=\"prev\" (click)=\"handleSettingsDialogOpenClose(false)\"></button>\n <p>\n <strong>Console Settings</strong>\n </p>\n </header>\n\n <div class=\"settings-form\">\n <h4>Behavior</h4>\n <fieldset>\n <label>\n <input #inputAllowLocalClipboardWrite type=\"checkbox\" name=\"allowLocalClipboardWrite\"\n [checked]=\"consoleContext().userSettings.settings().console.allowCopyToLocalClipboard\"\n (change)=\"handleSettingsAllowLocalClipboardWrite(inputAllowLocalClipboardWrite.checked)\" />\n Allow the remote machine to copy text to my local clipboard\n </label>\n <label>\n <input #inputScaleToContainerSize type=\"checkbox\" name=\"scaleToContainerSize\"\n [checked]=\"consoleContext().userSettings.settings().console.preserveAspectRatioOnScale\"\n (change)=\"handleSettingsPreserveAspectRatioChange(inputScaleToContainerSize.checked)\" />\n Preserve console aspect ratio when scaling size\n </label>\n </fieldset>\n\n <div class=\"settings-toolbar-dock\">\n <h4>Toolbar Position</h4>\n <div role=\"group\">\n <button (click)=\"handleChangeToolbarPosition('left')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'left'\">Left</button>\n <button (click)=\"handleChangeToolbarPosition('right')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'right'\">Right</button>\n <button (click)=\"handleChangeToolbarPosition('top')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'top'\">Top</button>\n <button (click)=\"handleChangeToolbarPosition('bottom')\"\n [disabled]=\"consoleContext().userSettings.settings().toolbar.dockTo === 'bottom'\">Bottom</button>\n </div>\n </div>\n </div>\n </article>\n</dialog>\n", styles: ["@charset \"UTF-8\";:root,:host{--pico-font-family-emoji: \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";--pico-font-family-sans-serif: system-ui, \"Segoe UI\", Roboto, Oxygen, Ubuntu, Cantarell, Helvetica, Arial, \"Helvetica Neue\", sans-serif, var(--pico-font-family-emoji);--pico-font-family-monospace: ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, \"Liberation Mono\", monospace, var(--pico-font-family-emoji);--pico-font-family: var(--pico-font-family-sans-serif);--pico-line-height: 1.5;--pico-font-weight: 400;--pico-font-size: 100%;--pico-text-underline-offset: .1rem;--pico-border-radius: .25rem;--pico-border-width: .0625rem;--pico-outline-width: .125rem;--pico-transition: .2s ease-in-out;--pico-spacing: 1rem;--pico-typography-spacing-vertical: 1rem;--pico-block-spacing-vertical: var(--pico-spacing);--pico-block-spacing-horizontal: var(--pico-spacing);--pico-grid-column-gap: var(--pico-spacing);--pico-grid-row-gap: var(--pico-spacing);--pico-form-element-spacing-vertical: .75rem;--pico-form-element-spacing-horizontal: 1rem;--pico-group-box-shadow: 0 0 0 rgba(0, 0, 0, 0);--pico-group-box-shadow-focus-with-button: 0 0 0 var(--pico-outline-width) var(--pico-primary-focus);--pico-group-box-shadow-focus-with-input: 0 0 0 .0625rem var(--pico-form-element-border-color);--pico-modal-overlay-backdrop-filter: blur(.375rem);--pico-nav-element-spacing-vertical: 1rem;--pico-nav-element-spacing-horizontal: .5rem;--pico-nav-link-spacing-vertical: .5rem;--pico-nav-link-spacing-horizontal: .5rem;--pico-nav-breadcrumb-divider: \">\";--pico-icon-checkbox: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E\");--pico-icon-minus: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='5' y1='12' x2='19' y2='12'%3E%3C/line%3E%3C/svg%3E\");--pico-icon-chevron: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(136, 145, 164)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E\");--pico-icon-date: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(136, 145, 164)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E\");--pico-icon-time: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(136, 145, 164)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cpolyline points='12 6 12 12 16 14'%3E%3C/polyline%3E%3C/svg%3E\");--pico-icon-search: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(136, 145, 164)' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E\");--pico-icon-close: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(136, 145, 164)' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'%3E%3C/line%3E%3Cline x1='6' y1='6' x2='18' y2='18'%3E%3C/line%3E%3C/svg%3E\");--pico-icon-loading: url(\"data:image/svg+xml,%3Csvg fill='none' height='24' width='24' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg' %3E%3Cstyle%3E g %7B animation: rotate 2s linear infinite; transform-origin: center center; %7D circle %7B stroke-dasharray: 75,100; stroke-dashoffset: -5; animation: dash 1.5s ease-in-out infinite; stroke-linecap: round; %7D @keyframes rotate %7B 0%25 %7B transform: rotate(0deg); %7D 100%25 %7B transform: rotate(360deg); %7D %7D @keyframes dash %7B 0%25 %7B stroke-dasharray: 1,100; stroke-dashoffset: 0; %7D 50%25 %7B stroke-dasharray: 44.5,100; stroke-dashoffset: -17.5; %7D 100%25 %7B stroke-dasharray: 44.5,100; stroke-dashoffset: -62; %7D %7D %3C/style%3E%3Cg%3E%3Ccircle cx='12' cy='12' r='10' fill='none' stroke='rgb(136, 145, 164)' stroke-width='4' /%3E%3C/g%3E%3C/svg%3E\")}@media (min-width: 576px){:root,:host{--pico-font-size: 106.25%}}@media (min-width: 768px){:root,:host{--pico-font-size: 112.5%}}@media (min-width: 1024px){:root,:host{--pico-font-size: 118.75%}}@media (min-width: 1280px){:root,:host{--pico-font-size: 125%}}@media (min-width: 1536px){:root,:host{--pico-font-size: 131.25%}}a,a.secondary,a.contrast{--pico-text-decoration: underline}small{--pico-font-size: .875em}h1,h2,h3,h4,h5,h6{--pico-font-weight: 700}h1{--pico-font-size: 2rem;--pico-line-height: 1.125;--pico-typography-spacing-top: 3rem}h2{--pico-font-size: 1.75rem;--pico-line-height: 1.15;--pico-typography-spacing-top: 2.625rem}h3{--pico-font-size: 1.5rem;--pico-line-height: 1.175;--pico-typography-spacing-top: 2.25rem}h4{--pico-font-size: 1.25rem;--pico-line-height: 1.2;--pico-typography-spacing-top: 1.874rem}h5{--pico-font-size: 1.125rem;--pico-line-height: 1.225;--pico-typography-spacing-top: 1.6875rem}h6{--pico-font-size: 1rem;--pico-line-height: 1.25;--pico-typography-spacing-top: 1.5rem}thead th,thead td,tfoot th,tfoot td{--pico-font-weight: 600;--pico-border-width: .1875rem}pre,code,kbd,samp{--pico-font-family: var(--pico-font-family-monospace)}kbd{--pico-font-weight: bolder}input:not([type=submit],[type=button],[type=reset],[type=checkbox],[type=radio],[type=file]),:where(select,textarea){--pico-outline-width: .0625rem}[type=search]{--pico-border-radius: 5rem}[type=checkbox],[type=radio]{--pico-border-width: .125rem}[type=checkbox][role=switch]{--pico-border-width: .1875rem}details.dropdown summary:not([role=button]){--pico-outline-width: .0625rem}nav details.dropdown summary:focus-visible{--pico-outline-width: .125rem}[role=search]{--pico-border-radius: 5rem}[role=search]:has(button.secondary:focus,[type=submit].secondary:focus,[type=button].secondary:focus,[role=button].secondary:focus),[role=group]:has(button.secondary:focus,[type=submit].secondary:focus,[type=button].secondary:focus,[role=button].secondary:focus){--pico-group-box-shadow-focus-with-button: 0 0 0 var(--pico-outline-width) var(--pico-secondary-focus)}[role=search]:has(button.contrast:focus,[type=submit].contrast:focus,[type=button].contrast:focus,[role=button].contrast:focus),[role=group]:has(button.contrast:focus,[type=submit].contrast:focus,[type=button].contrast:focus,[role=button].contrast:focus){--pico-group-box-shadow-focus-with-button: 0 0 0 var(--pico-outline-width) var(--pico-contrast-focus)}[role=search] button,[role=search] [type=submit],[role=search] [type=button],[role=search] [role=button],[role=group] button,[role=group] [type=submit],[role=group] [type=button],[role=group] [role=button]{--pico-form-element-spacing-horizontal: 2rem}details summary[role=button]:not(.outline):after{filter:brightness(0) invert(1)}[aria-busy=true]:not(input,select,textarea):is(button,[type=submit],[type=button],[type=reset],[role=button]):not(.outline):before{filter:brightness(0) invert(1)}[data-theme=light],:root:not([data-theme=dark]),:host(:not([data-theme=dark])){color-scheme:light;--pico-background-color: #fff;--pico-color: #373c44;--pico-text-selection-color: rgba(2, 154, 232, .25);--pico-muted-color: #646b79;--pico-muted-border-color: rgb(231, 234, 239.5);--pico-primary: #0172ad;--pico-primary-background: #0172ad;--pico-primary-border: var(--pico-primary-background);--pico-primary-underline: rgba(1, 114, 173, .5);--pico-primary-hover: #015887;--pico-primary-hover-background: #02659a;--pico-primary-hover-border: var(--pico-primary-hover-background);--pico-primary-hover-underline: var(--pico-primary-hover);--pico-primary-focus: rgba(2, 154, 232, .5);--pico-primary-inverse: #fff;--pico-secondary: #5d6b89;--pico-secondary-background: #525f7a;--pico-secondary-border: var(--pico-secondary-background);--pico-secondary-underline: rgba(93, 107, 137, .5);--pico-secondary-hover: #48536b;--pico-secondary-hover-background: #48536b;--pico-secondary-hover-border: var(--pico-secondary-hover-background);--pico-secondary-hover-underline: var(--pico-secondary-hover);--pico-secondary-focus: rgba(93, 107, 137, .25);--pico-secondary-inverse: #fff;--pico-contrast: #181c25;--pico-contrast-background: #181c25;--pico-contrast-border: var(--pico-contrast-background);--pico-contrast-underline: rgba(24, 28, 37, .5);--pico-contrast-hover: #000;--pico-contrast-hover-background: #000;--pico-contrast-hover-border: var(--pico-contrast-hover-background);--pico-contrast-hover-underline: var(--pico-secondary-hover);--pico-contrast-focus: rgba(93, 107, 137, .25);--pico-contrast-inverse: #fff;--pico-box-shadow: .0145rem .029rem .174rem rgba(129, 145, 181, .01698), .0335rem .067rem .402rem rgba(129, 145, 181, .024), .0625rem .125rem .75rem rgba(129, 145, 181, .03), .1125rem .225rem 1.35rem rgba(129, 145, 181, .036), .2085rem .417rem 2.502rem rgba(129, 145, 181, .04302), .5rem 1rem 6rem rgba(129, 145, 181, .06), 0 0 0 .0625rem rgba(129, 145, 181, .015);--pico-h1-color: #2d3138;--pico-h2-color: #373c44;--pico-h3-color: #424751;--pico-h4-color: #4d535e;--pico-h5-color: #5c6370;--pico-h6-color: #646b79;--pico-mark-background-color: rgb(252.5, 230.5, 191.5);--pico-mark-color: #0f1114;--pico-ins-color: rgb(28.5, 105.5, 84);--pico-del-color: rgb(136, 56.5, 53);--pico-blockquote-border-color: var(--pico-muted-border-color);--pico-blockquote-footer-color: var(--pico-muted-color);--pico-button-box-shadow: 0 0 0 rgba(0, 0, 0, 0);--pico-button-hover-box-shadow: 0 0 0 rgba(0, 0, 0, 0);--pico-table-border-color: var(--pico-muted-border-color);--pico-table-row-stripped-background-color: rgba(111, 120, 135, .0375);--pico-code-background-color: rgb(243, 244.5, 246.75);--pico-code-color: #646b79;--pico-code-kbd-background-color: var(--pico-color);--pico-code-kbd-color: var(--pico-background-color);--pico-form-element-background-color: rgb(251, 251.5, 252.25);--pico-form-element-selected-background-color: #dfe3eb;--pico-form-element-border-color: #cfd5e2;--pico-form-element-color: #23262c;--pico-form-element-placeholder-color: var(--pico-muted-color);--pico-form-element-active-background-color: #fff;--pico-form-element-active-border-color: var(--pico-primary-border);--pico-form-element-focus-color: var(--pico-primary-border);--pico-form-element-disabled-opacity: .5;--pico-form-element-invalid-border-color: rgb(183.5, 105.5, 106.5);--pico-form-element-invalid-active-border-color: rgb(200.25, 79.25, 72.25);--pico-form-element-invalid-focus-color: var(--pico-form-element-invalid-active-border-color);--pico-form-element-valid-border-color: rgb(76, 154.5, 137.5);--pico-form-element-valid-active-border-color: rgb(39, 152.75, 118.75);--pico-form-element-valid-focus-color: var(--pico-form-element-valid-active-border-color);--pico-switch-background-color: #bfc7d9;--pico-switch-checked-background-color: var(--pico-primary-background);--pico-switch-color: #fff;--pico-switch-thumb-box-shadow: 0 0 0 rgba(0, 0, 0, 0);--pico-range-border-color: #dfe3eb;--pico-range-active-border-color: #bfc7d9;--pico-range-thumb-border-color: var(--pico-background-color);--pico-range-thumb-color: var(--pico-secondary-background);--pico-range-thumb-active-color: var(--pico-primary-background);--pico-accordion-border-color: var(--pico-muted-border-color);--pico-accordion-active-summary-color: var(--pico-primary-hover);--pico-accordion-close-summary-color: var(--pico-color);--pico-accordion-open-summary-color: var(--pico-muted-color);--pico-card-background-color: var(--pico-background-color);--pico-card-border-color: var(--pico-muted-border-color);--pico-card-box-shadow: var(--pico-box-shadow);--pico-card-sectioning-background-color: rgb(251, 251.5, 252.25);--pico-dropdown-background-color: #fff;--pico-dropdown-border-color: #eff1f4;--pico-dropdown-box-shadow: var(--pico-box-shadow);--pico-dropdown-color: var(--pico-color);--pico-dropdown-hover-background-color: #eff1f4;--pico-loading-spinner-opacity: .5;--pico-modal-overlay-background-color: rgba(232, 234, 237, .75);--pico-progress-background-color: #dfe3eb;--pico-progress-color: var(--pico-primary-background);--pico-tooltip-background-color: var(--pico-contrast-background);--pico-tooltip-color: var(--pico-contrast-inverse);--pico-icon-valid: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(76, 154.5, 137.5)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E\");--pico-icon-invalid: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(200.25, 79.25, 72.25)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E\")}[data-theme=light] input:is([type=submit],[type=button],[type=reset],[type=checkbox],[type=radio],[type=file]),:root:not([data-theme=dark]) input:is([type=submit],[type=button],[type=reset],[type=checkbox],[type=radio],[type=file]),:host(:not([data-theme=dark])) input:is([type=submit],[type=button],[type=reset],[type=checkbox],[type=radio],[type=file]){--pico-form-element-focus-color: var(--pico-primary-focus)}@media only screen and (prefers-color-scheme: dark){:root:not([data-theme]),:host(:not([data-theme])){color-scheme:dark;--pico-background-color: rgb(19, 22.5, 30.5);--pico-color: #c2c7d0;--pico-text-selection-color: rgba(1, 170, 255, .1875);--pico-muted-color: #7b8495;--pico-muted-border-color: #202632;--pico-primary: #01aaff;--pico-primary-background: #0172ad;--pico-primary-border: var(--pico-primary-background);--pico-primary-underline: rgba(1, 170, 255, .5);--pico-primary-hover: #79c0ff;--pico-primary-hover-background: #017fc0;--pico-primary-hover-border: var(--pico-primary-hover-background);--pico-primary-hover-underline: var(--pico-primary-hover);--pico-primary-focus: rgba(1, 170, 255, .375);--pico-primary-inverse: #fff;--pico-secondary: #969eaf;--pico-secondary-background: #525f7a;--pico-secondary-border: var(--pico-secondary-background);--pico-secondary-underline: rgba(150, 158, 175, .5);--pico-secondary-hover: #b3b9c5;--pico-secondary-hover-background: #5d6b89;--pico-secondary-hover-border: var(--pico-secondary-hover-background);--pico-secondary-hover-underline: var(--pico-secondary-hover);--pico-secondary-focus: rgba(144, 158, 190, .25);--pico-secondary-inverse: #fff;--pico-contrast: #dfe3eb;--pico-contrast-background: #eff1f4;--pico-contrast-border: var(--pico-contrast-background);--pico-contrast-underline: rgba(223, 227, 235, .5);--pico-contrast-hover: #fff;--pico-contrast-hover-background: #fff;--pico-contrast-hover-border: var(--pico-contrast-hover-background);--pico-contrast-hover-underline: var(--pico-contrast-hover);--pico-contrast-focus: rgba(207, 213, 226, .25);--pico-contrast-inverse: #000;--pico-box-shadow: .0145rem .029rem .174rem rgba(7, 8.5, 12, .01698), .0335rem .067rem .402rem rgba(7, 8.5, 12, .024), .0625rem .125rem .75rem rgba(7, 8.5, 12, .03), .1125rem .225rem 1.35rem rgba(7, 8.5, 12, .036), .2085rem .417rem 2.502rem rgba(7, 8.5, 12, .04302), .5rem 1rem 6rem rgba(7, 8.5, 12, .06), 0 0 0 .0625rem rgba(7, 8.5, 12, .015);--pico-h1-color: #f0f1f3;--pico-h2-color: #e0e3e7;--pico-h3-color: #c2c7d0;--pico-h4-color: #b3b9c5;--pico-h5-color: #a4acba;--pico-h6-color: #8891a4;--pico-mark-background-color: #014063;--pico-mark-color: #fff;--pico-ins-color: #62af9a;--pico-del-color: rgb(205.5, 126, 123);--pico-blockquote-border-color: var(--pico-muted-border-color);--pico-blockquote-footer-color: var(--pico-muted-color);--pico-button-box-shadow: 0 0 0 rgba(0, 0, 0, 0);--pico-button-hover-box-shadow: 0 0 0 rgba(0, 0, 0, 0);--pico-table-border-color: var(--pico-muted-border-color);--pico-table-row-stripped-background-color: rgba(111, 120, 135, .0375);--pico-code-background-color: rgb(26, 30.5, 40.25);--pico-code-color: #8891a4;--pico-code-kbd-background-color: var(--pico-color);--pico-code-kbd-color: var(--pico-background-color);--pico-form-element-background-color: rgb(28, 33, 43.5);--pico-form-element-selected-background-color: #2a3140;--pico-form-element-border-color: #2a3140;--pico-form-element-color: #e0e3e7;--pico-form-element-placeholder-color: #8891a4;--pico-form-element-active-background-color: rgb(26, 30.5, 40.25);--pico-form-element-active-border-color: var(--pico-primary-border);--pico-form-element-focus-color: var(--pico-primary-border);--pico-form-element-disabled-opacity: .5;--pico-form-element-invalid-border-color: rgb(149.5, 74, 80);--pico-form-element-invalid-active-border-color: rgb(183.25, 63.5, 59);--pico-form-element-invalid-focus-color: var(--pico-form-element-invalid-active-border-color);--pico-form-element-valid-border-color: #2a7b6f;--pico-form-element-valid-active-border-color: rgb(22, 137, 105.5);--pico-form-element-valid-focus-color: var(--pico-form-element-valid-active-border-color);--pico-switch-background-color: #333c4e;--pico-switch-checked-background-color: var(--pico-primary-background);--pico-switch-color: #fff;--pico-switch-thumb-box-shadow: 0 0 0 rgba(0, 0, 0, 0);--pico-range-border-color: #202632;--pico-range-active-border-color: #2a3140;--pico-range-thumb-border-color: var(--pico-background-color);--pico-range-thumb-color: var(--pico-secondary-background);--pico-range-thumb-active-color: var(--pico-primary-background);--pico-accordion-border-color: var(--pico-muted-border-color);--pico-accordion-active-summary-color: var(--pico-primary-hover);--pico-accordion-close-summary-color: var(--pico-color);--pico-accordion-open-summary-color: var(--pico-muted-color);--pico-card-background-color: #181c25;--pico-card-border-color: var(--pico-card-background-color);--pico-card-box-shadow: var(--pico-box-shadow);--pico-card-sectioning-background-color: rgb(26, 30.5, 40.25);--pico-dropdown-background-color: #181c25;--pico-dropdown-border-color: #202632;--pico-dropdown-box-shadow: var(--pico-box-shadow);--pico-dropdown-color: var(--pico-color);--pico-dropdown-hover-background-color: #202632;--pico-loading-spinner-opacity: .5;--pico-modal-overlay-background-color: rgba(7.5, 8.5, 10, .75);--pico-progress-background-color: #202632;--pico-progress-color: var(--pico-primary-background);--pico-tooltip-background-color: var(--pico-contrast-background);--pico-tooltip-color: var(--pico-contrast-inverse);--pico-icon-valid: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(42, 123, 111)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E\");--pico-icon-invalid: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(149.5, 74, 80)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E\")}:root:not([data-theme]) input:is([type=submit],[type=button],[type=reset],[type=checkbox],[type=radio],[type=file]),:host(:not([data-theme])) input:is([type=submit],[type=button],[type=reset],[type=checkbox],[type=radio],[type=file]){--pico-form-element-focus-color: var(--pico-primary-focus)}:root:not([data-theme]) details summary[role=button].contrast:not(.outline):after,:host(:not([data-theme])) details summary[role=button].contrast:not(.outline):after{filter:brightness(0)}:root:not([data-theme]) [aria-busy=true]:not(input,select,textarea).contrast:is(button,[type=submit],[type=button],[type=reset],[role=button]):not(.outline):before,:host(:not([data-theme])) [aria-busy=true]:not(input,select,textarea).contrast:is(button,[type=submit],[type=button],[type=reset],[role=button]):not(.outline):before{filter:brightness(0)}}[data-theme=dark]{color-scheme:dark;--pico-background-color: rgb(19, 22.5, 30.5);--pico-color: #c2c7d0;--pico-text-selection-color: rgba(1, 170, 255, .1875);--pico-muted-color: #7b8495;--pico-muted-border-color: #202632;--pico-primary: #01aaff;--pico-primary-background: #0172ad;--pico-primary-border: var(--pico-primary-background);--pico-primary-underline: rgba(1, 170, 255, .5);--pico-primary-hover: #79c0ff;--pico-primary-hover-background: #017fc0;--pico-primary-hover-border: var(--pico-primary-hover-background);--pico-primary-hover-underline: var(--pico-primary-hover);--pico-primary-focus: rgba(1, 170, 255, .375);--pico-primary-inverse: #fff;--pico-secondary: #969eaf;--pico-secondary-background: #525f7a;--pico-secondary-border: var(--pico-secondary-background);--pico-secondary-underline: rgba(150, 158, 175, .5);--pico-secondary-hover: #b3b9c5;--pico-secondary-hover-background: #5d6b89;--pico-secondary-hover-border: var(--pico-secondary-hover-background);--pico-secondary-hover-underline: var(--pico-secondary-hover);--pico-secondary-focus: rgba(144, 158, 190, .25);--pico-secondary-inverse: #fff;--pico-contrast: #dfe3eb;--pico-contrast-background: #eff1f4;--pico-contrast-border: var(--pico-contrast-background);--pico-contrast-underline: rgba(223, 227, 235, .5);--pico-contrast-hover: #fff;--pico-contrast-hover-background: #fff;--pico-contrast-hover-border: var(--pico-contrast-hover-background);--pico-contrast-hover-underline: var(--pico-contrast-hover);--pico-contrast-focus: rgba(207, 213, 226, .25);--pico-contrast-inverse: #000;--pico-box-shadow: .0145rem .029rem .174rem rgba(7, 8.5, 12, .01698), .0335rem .067rem .402rem rgba(7, 8.5, 12, .024), .0625rem .125rem .75rem rgba(7, 8.5, 12, .03), .1125rem .225rem 1.35rem rgba(7, 8.5, 12, .036), .2085rem .417rem 2.502rem rgba(7, 8.5, 12, .04302), .5rem 1rem 6rem rgba(7, 8.5, 12, .06), 0 0 0 .0625rem rgba(7, 8.5, 12, .015);--pico-h1-color: #f0f1f3;--pico-h2-color: #e0e3e7;--pico-h3-color: #c2c7d0;--pico-h4-color: #b3b9c5;--pico-h5-color: #a4acba;--pico-h6-color: #8891a4;--pico-mark-background-color: #014063;--pico-mark-color: #fff;--pico-ins-color: #62af9a;--pico-del-color: rgb(205.5, 126, 123);--pico-blockquote-border-color: var(--pico-muted-border-color);--pico-blockquote-footer-color: var(--pico-muted-color);--pico-button-box-shadow: 0 0 0 rgba(0, 0, 0, 0);--pico-button-hover-box-shadow: 0 0 0 rgba(0, 0, 0, 0);--pico-table-border-color: var(--pico-muted-border-color);--pico-table-row-stripped-background-color: rgba(111, 120, 135, .0375);--pico-code-background-color: rgb(26, 30.5, 40.25);--pico-code-color: #8891a4;--pico-code-kbd-background-color: var(--pico-color);--pico-code-kbd-color: var(--pico-background-color);--pico-form-element-background-color: rgb(28, 33, 43.5);--pico-form-element-selected-background-color: #2a3140;--pico-form-element-border-color: #2a3140;--pico-form-element-color: #e0e3e7;--pico-form-element-placeholder-color: #8891a4;--pico-form-element-active-background-color: rgb(26, 30.5, 40.25);--pico-form-element-active-border-color: var(--pico-primary-border);--pico-form-element-focus-color: var(--pico-primary-border);--pico-form-element-disabled-opacity: .5;--pico-form-element-invalid-border-color: rgb(149.5, 74, 80);--pico-form-element-invalid-active-border-color: rgb(183.25, 63.5, 59);--pico-form-element-invalid-focus-color: var(--pico-form-element-invalid-active-border-color);--pico-form-element-valid-border-color: #2a7b6f;--pico-form-element-valid-active-border-color: rgb(22, 137, 105.5);--pico-form-element-valid-focus-color: var(--pico-form-element-valid-active-border-color);--pico-switch-background-color: #333c4e;--pico-switch-checked-background-color: var(--pico-primary-background);--pico-switch-color: #fff;--pico-switch-thumb-box-shadow: 0 0 0 rgba(0, 0, 0, 0);--pico-range-border-color: #202632;--pico-range-active-border-color: #2a3140;--pico-range-thumb-border-color: var(--pico-background-color);--pico-range-thumb-color: var(--pico-secondary-background);--pico-range-thumb-active-color: var(--pico-primary-background);--pico-accordion-border-color: var(--pico-muted-border-color);--pico-accordion-active-summary-color: var(--pico-primary-hover);--pico-accordion-close-summary-color: var(--pico-color);--pico-accordion-open-summary-color: var(--pico-muted-color);--pico-card-background-color: #181c25;--pico-card-border-color: var(--pico-card-background-color);--pico-card-box-shadow: var(--pico-box-shadow);--pico-card-sectioning-background-color: rgb(26, 30.5, 40.25);--pico-dropdown-background-color: #181c25;--pico-dropdown-border-color: #202632;--pico-dropdown-box-shadow: var(--pico-box-shadow);--pico-dropdown-color: var(--pico-color);--pico-dropdown-hover-background-color: #202632;--pico-loading-spinner-opacity: .5;--pico-modal-overlay-background-color: rgba(7.5, 8.5, 10, .75);--pico-progress-background-color: #202632;--pico-progress-color: var(--pico-primary-background);--pico-tooltip-background-color: var(--pico-contrast-background);--pico-tooltip-color: var(--pico-contrast-inverse);--pico-icon-valid: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(42, 123, 111)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E\");--pico-icon-invalid: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(149.5, 74, 80)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E\")}[data-theme=dark] input:is([type=submit],[type=button],[type=reset],[type=checkbox],[type=radio],[type=file]){--pico-form-element-focus-color: var(--pico-primary-focus)}[data-theme=dark] details summary[role=button].contrast:not(.outline):after{filter:brightness(0)}[data-theme=dark] [aria-busy=true]:not(input,select,textarea).contrast:is(button,[type=submit],[type=button],[type=reset],[role=button]):not(.outline):before{filter:brightness(0)}progress,[type=checkbox],[type=radio],[type=range]{accent-color:var(--pico-primary)}*,*:before,*:after{box-sizing:border-box;background-repeat:no-repeat}:before,:after{text-decoration:inherit;vertical-align:inherit}:where(:root),:where(:host){-webkit-tap-highlight-color:transparent;-webkit-text-size-adjust:100%;text-size-adjust:100%;background-color:var(--pico-background-color);color:var(--pico-color);font-weight:var(--pico-font-weight);font-size:var(--pico-font-size);line-height:var(--pico-line-height);font-family:var(--pico-font-family);text-underline-offset:var(--pico-text-underline-offset);text-rendering:optimizeLegibility;overflow-wrap:break-word;tab-size:4}body{width:100%;margin:0}main{display:block}body>header,body>main,body>footer{padding-block:var(--pico-block-spacing-vertical)}section{margin-bottom:var(--pico-block-spacing-vertical)}.container,.container-fluid{width:100%;margin-right:auto;margin-left:auto;padding-right:var(--pico-spacing);padding-left:var(--pico-spacing)}@media (min-width: 576px){.container{max-width:510px;padding-right:0;padding-left:0}}@media (min-width: 768px){.container{max-width:700px}}@media (min-width: 1024px){.container{max-width:950px}}@media (min-width: 1280px){.container{max-width:1200px}}@media (min-width: 1536px){.container{max-width:1450px}}.grid{grid-column-gap:var(--pico-grid-column-gap);grid-row-gap:var(--pico-grid-row-gap);display:grid;grid-template-columns:1fr}@media (min-width: 768px){.grid{grid-template-columns:repeat(auto-fit,minmax(0%,1fr))}}.grid>*{min-width:0}.overflow-auto{overflow:auto}b,strong{font-weight:bolder}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}address,blockquote,dl,ol,p,pre,table,ul{margin-top:0;margin-bottom:var(--pico-typography-spacing-vertical);color:var(--pico-color);font-style:normal;font-weight:var(--pico-font-weight)}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:var(--pico-typography-spacing-vertical);color:var(--pico-color);font-weight:var(--pico-font-weight);font-size:var(--pico-font-size);line-height:var(--pico-line-height);font-family:var(--pico-font-family)}h1{--pico-color: var(--pico-h1-color)}h2{--pico-color: var(--pico-h2-color)}h3{--pico-color: var(--pico-h3-color)}h4{--pico-color: var(--pico-h4-color)}h5{--pico-color: var(--pico-h5-color)}h6{--pico-color: var(--pico-h6-color)}:where(article,address,blockquote,dl,figure,form,ol,p,pre,table,ul)~:is(h1,h2,h3,h4,h5,h6){margin-top:var(--pico-typography-spacing-top)}p{margin-bottom:var(--pico-typography-spacing-vertical)}hgroup{margin-bottom:var(--pico-typography-spacing-vertical)}hgroup>*{margin-top:0;margin-bottom:0}hgroup>*:not(:first-child):last-child{--pico-color: var(--pico-muted-color);--pico-font-weight: unset;font-size:1rem}:where(ol,ul) li{margin-bottom:calc(var(--pico-typography-spacing-vertical) * .25)}:where(dl,ol,ul) :where(dl,ol,ul){margin:0;margin-top:calc(var(--pico-typography-spacing-vertical) * .25)}ul li{list-style:square}mark{padding:.125rem .25rem;background-color:var(--pico-mark-background-color);color:var(--pico-mark-color);vertical-align:baseline}blockquote{display:block;margin:var(--pico-typography-spacing-vertical) 0;padding:var(--pico-spacing);border-right:none;border-left:.25rem solid var(--pico-blockquote-border-color);border-inline-start:.25rem solid var(--pico-blockquote-border-color);border-inline-end:none}blockquote footer{margin-top:calc(var(--pico-typography-spacing-vertical) * .5);color:var(--pico-blockquote-footer-color)}abbr[title]{border-bottom:1px dotted;text-decoration:none;cursor:help}ins{color:var(--pico-ins-color);text-decoration:none}del{color:var(--pico-del-color)}::selection{background-color:var(--pico-text-selection-color)}:where(a:not([role=button])),[role=link]{--pico-color: var(--pico-primary);--pico-background-color: transparent;--pico-underline: var(--pico-primary-underline);outline:none;background-color:var(--pico-background-color);color:var(--pico-color);text-decoration:var(--pico-text-decoration);text-decoration-color:var(--pico-underline);text-underline-offset:.125em;transition:background-color var(--pico-transition),color var(--pico-transition),text-decoration var(--pico-transition),box-shadow var(--pico-transition)}:where(a:not([role=button])):is([aria-current]:not([aria-current=false]),:hover,:active,:focus),[role=link]:is([aria-current]:not([aria-current=false]),:hover,:active,:focus){--pico-color: var(--pico-primary-hover);--pico-underline: var(--pico-primary-hover-underline);--pico-text-decoration: underline}:where(a:not([role=button])):focus-visible,[role=link]:focus-visible{box-shadow:0 0 0 var(--pico-outline-width) var(--pico-primary-focus)}:where(a:not([role=button])).secondary,[role=link].secondary{--pico-color: var(--pico-secondary);--pico-underline: var(--pico-secondary-underline)}:where(a:not([role=button])).secondary:is([aria-current]:not([aria-current=false]),:hover,:active,:focus),[role=link].secondary:is([aria-current]:not([aria-current=false]),:hover,:active,:focus){--pico-color: var(--pico-secondary-hover);--pico-underline: var(--pico-secondary-hover-underline)}:where(a:not([role=button])).contrast,[role=link].contrast{--pico-color: var(--pico-contrast);--pico-underline: var(--pico-contrast-underline)}:where(a:not([role=button])).contrast:is([aria-current]:not([aria-current=false]),:hover,:active,:focus),[role=link].contrast:is([aria-current]:not([aria-current=false]),:hover,:active,:focus){--pico-color: var(--pico-contrast-hover);--pico-underline: var(--pico-contrast-hover-underline)}a[role=button]{display:inline-block}button{margin:0;overflow:visible;font-family:inherit;text-transform:none}button,[type=submit],[type=reset],[type=button]{-webkit-appearance:button}button,[type=submit],[type=reset],[type=button],[type=file]::file-selector-button,[role=button]{--pico-background-color: var(--pico-primary-background);--pico-border-color: var(--pico-primary-border);--pico-color: var(--pico-primary-inverse);--pico-box-shadow: var(--pico-button-box-shadow, 0 0 0 rgba(0, 0, 0, 0));padding:var(--pico-form-element-spacing-vertical) var(--pico-form-element-spacing-horizontal);border:var(--pico-border-width) solid var(--pico-border-color);border-radius:var(--pico-border-radius);outline:none;background-color:var(--pico-background-color);box-shadow:var(--pico-box-shadow);color:var(--pico-color);font-weight:var(--pico-font-weight);font-size:1rem;line-height:var(--pico-line-height);text-align:center;text-decoration:none;cursor:pointer;-webkit-user-select:none;user-select:none;transition:background-color var(--pico-transition),border-color var(--pico-transition),color var(--pico-transition),box-shadow var(--pico-transition)}button:is([aria-current]:not([aria-current=false])),button:is(:hover,:active,:focus),[type=submit]:is([aria-current]:not([aria-current=false])),[type=submit]:is(:hover,:active,:focus),[type=reset]:is([aria-current]:not([aria-current=false])),[type=reset]:is(:hover,:active,:focus),[type=button]:is([aria-current]:not([aria-current=false])),[type=button]:is(:hover,:active,:focus),[type=file]::file-selector-button:is([aria-current]:not([aria-current=false])),[type=file]::file-selector-button:is(:hover,:active,:focus),[role=button]:is([aria-current]:not([aria-current=false])),[role=button]:is(:hover,:active,:focus){--pico-background-color: var(--pico-primary-hover-background);--pico-border-color: var(--pico-primary-hover-border);--pico-box-shadow: var(--pico-button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0));--pico-color: var(--pico-primary-inverse)}button:focus,button:is([aria-current]:not([aria-current=false])):focus,[type=submit]:focus,[type=submit]:is([aria-current]:not([aria-current=false])):focus,[type=reset]:focus,[type=reset]:is([aria-current]:not([aria-current=false])):focus,[type=button]:focus,[type=button]:is([aria-current]:not([aria-current=false])):focus,[type=file]::file-selector-button:focus,[type=file]::file-selector-button:is([aria-current]:not([aria-current=false])):focus,[role=button]:focus,[role=button]:is([aria-current]:not([aria-current=false])):focus{--pico-box-shadow: var(--pico-button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)), 0 0 0 var(--pico-outline-width) var(--pico-primary-focus)}[type=submit],[type=reset],[type=button]{margin-bottom:var(--pico-spacing)}:is(button,[type=submit],[type=button],[role=button]).secondary,[type=reset],[type=file]::file-selector-button{--pico-background-color: var(--pico-secondary-background);--pico-border-color: var(--pico-secondary-border);--pico-color: var(--pico-secondary-inverse);cursor:pointer}:is(button,[type=submit],[type=button],[role=button]).secondary:is([aria-current]:not([aria-current=false]),:hover,:active,:focus),[type=reset]:is([aria-current]:not([aria-current=false]),:hover,:active,:focus),[type=file]::file-selector-button:is([aria-current]:not([aria-current=false]),:hover,:active,:focus){--pico-background-color: var(--pico-secondary-hover-background);--pico-border-color: var(--pico-secondary-hover-border);--pico-color: var(--pico-secondary-inverse)}:is(button,[type=submit],[type=button],[role=button]).secondary:focus,:is(button,[type=submit],[type=button],[role=button]).secondary:is([aria-current]:not([aria-current=false])):focus,[type=reset]:focus,[type=reset]:is([aria-current]:not([aria-current=false])):focus,[type=file]::file-selector-button:focus,[type=file]::file-selector-button:is([aria-current]:not([aria-current=false])):focus{--pico-box-shadow: var(--pico-button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)), 0 0 0 var(--pico-outline-width) var(--pico-secondary-focus)}:is(button,[type=submit],[type=button],[role=button]).contrast{--pico-background-color: var(--pico-contrast-background);--pico-border-color: var(--pico-contrast-border);--pico-color: var(--pico-contrast-inverse)}:is(button,[type=submit],[type=button],[role=button]).contrast:is([aria-current]:not([aria-current=false]),:hover,:active,:focus){--pico-background-color: var(--pico-contrast-hover-background);--pico-border-color: var(--pico-contrast-hover-border);--pico-color: var(--pico-contrast-inverse)}:is(button,[type=submit],[type=button],[role=button]).contrast:focus,:is(button,[type=submit],[type=button],[role=button]).contrast:is([aria-current]:not([aria-current=false])):focus{--pico-box-shadow: var(--pico-button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)), 0 0 0 var(--pico-outline-width) var(--pico-contrast-focus)}:is(button,[type=submit],[type=button],[role=button]).outline,[type=reset].outline{--pico-background-color: transparent;--pico-color: var(--pico-primary);--pico-border-color: var(--pico-primary)}:is(button,[type=submit],[type=button],[role=button]).outline:is([aria-current]:not([aria-current=false]),:hover,:active,:focus),[type=reset].outline:is([aria-current]:not([aria-current=false]),:hover,:active,:focus){--pico-background-color: transparent;--pico-color: var(--pico-primary-hover);--pico-border-color: var(--pico-primary-hover)}:is(button,[type=submit],[type=button],[role=button]).outline.secondary,[type=reset].outline{--pico-color: var(--pico-secondary);--pico-border-color: var(--pico-secondary)}:is(button,[type=submit],[type=button],[role=button]).outline.secondary:is([aria-current]:not([aria-current=false]),:hover,:active,:focus),[type=reset].outline:is([aria-current]:not([aria-current=false]),:hover,:active,:focus){--pico-color: var(--pico-secondary-hover);--pico-border-color: var(--pico-secondary-hover)}:is(button,[type=submit],[type=button],[role=button]).outline.contrast{--pico-color: var(--pico-contrast);--pico-border-color: var(--pico-contrast)}:is(button,[type=submit],[type=button],[role=button]).outline.contrast:is([aria-current]:not([aria-current=false]),:hover,:active,:focus){--pico-color: var(--pico-contrast-hover);--pico-border-color: var(--pico-contrast-hover)}:where(button,[type=submit],[type=reset],[type=button],[role=button])[disabled],:where(fieldset[disabled]) :is(button,[type=submit],[type=button],[type=reset],[role=button]){opacity:.5;pointer-events:none}:where(table){width:100%;border-collapse:collapse;border-spacing:0;text-indent:0}th,td{padding:calc(var(--pico-spacing) / 2) var(--pico-spacing);border-bottom:var(--pico-border-width) solid var(--pico-table-border-color);background-color:var(--pico-background-color);color:var(--pico-color);font-weight:var(--pico-font-weight);text-align:left;text-align:start}tfoot th,tfoot td{border-top:var(--pico-border-width) solid var(--pico-table-border-color);border-bottom:0}table.striped tbody tr:nth-child(odd) th,table.striped tbody tr:nth-child(odd) td{background-color:var(--pico-table-row-stripped-background-color)}:where(audio,canvas,iframe,img,svg,video){vertical-align:middle}audio,video{display:inline-block}audio:not([controls]){display:none;height:0}:where(iframe){border-style:none}img{max-width:100%;height:auto;border-style:none}:where(svg:not([fill])){fill:currentColor}svg:not(:root),svg:not(:host){overflow:hidden}pre,code,kbd,samp{font-size:.875em;font-family:var(--pico-font-family)}pre code,pre samp{font-size:inherit;font-family:inherit}pre{-ms-overflow-style:scrollbar;overflow:auto}pre,code,kbd,samp{border-radius:var(--pico-border-radius);background:var(--pico-code-background-color);color:var(--pico-code-color);font-weight:var(--pico-font-weight);line-height:initial}code,kbd,samp{display:inline-block;padding:.375rem}pre{display:block;margin-bottom:var(--pico-spacing);overflow-x:auto}pre>code,pre>samp{display:block;padding:var(--pico-spacing);background:none;line-height:var(--pico-line-height)}kbd{background-color:var(--pico-code-kbd-background-color);color:var(--pico-code-kbd-color);vertical-align:baseline}figure{display:block;margin:0;padding:0}figure figcaption{padding:calc(var(--pico-spacing) * .5) 0;color:var(--pico-muted-color)}hr{height:0;margin:var(--pico-typography-spacing-vertical) 0;border:0;border-top:1px solid var(--pico-muted-border-color);color:inherit}[hidden],template{display:none!important}canvas{display:inline-block}input,optgroup,select,textarea{margin:0;font-size:1rem;line-height:var(--pico-line-height);font-family:inherit;letter-spacing:inherit}input{overflow:visible}select{text-transform:none}legend{max-width:100%;padding:0;color:inherit;white-space:normal}textarea{overflow:auto}[type=checkbox],[type=radio]{padding:0}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}::-moz-focus-inner{padding:0;border-style:none}:-moz-focusring{outline:none}:-moz-ui-invalid{box-shadow:none}::-ms-expand{display:none}[type=file],[type=range]{padding:0;border-width:0}input:not([type=checkbox],[type=radio],[type=range]){height:calc(1rem * var(--pico-line-height) + var(--pico-form-element-spacing-vertical) * 2 + var(--pico-border-width) * 2)}fieldset{width:100%;margin:0;margin-bottom:var(--pico-spacing);padding:0;border:0}label,fieldset legend{display:block;margin-bottom:calc(var(--pico-spacing) * .375);color:var(--pico-color);font-weight:var(--pico-form-label-font-weight, var(--pico-font-weight))}fieldset legend{margin-bottom:calc(var(--pico-spacing) * .5)}input:not([type=checkbox],[type=radio]),button[type=submit],select,textarea{width:100%}input:not([type=checkbox],[type=radio],[type=range],[type=file]),select,textarea{appearance:none;padding:var(--pico-form-element-spacing-vertical) var(--pico-form-element-spacing-horizontal)}input,select,textarea{--pico-background-color: var(--pico-form-element-background-color);--pico-border-color: var(--pico-form-element-border-color);--pico-color: var(--pico-form-element-color);--pico-box-shadow: none;border:var(--pico-border-width) solid var(--pico-border-color);border-radius:var(--pico-border-radius);outline:none;background-color:var(--pico-background-color);box-shadow:var(--pico-box-shadow);color:var(--pico-color);font-weight:var(--pico-font-weight);transition:background-color var(--pico-transition),border-color var(--pico-transition),color var(--pico-transition),box-shadow var(--pico-transition)}input:not([type=submit],[type=button],[type=reset],[type=checkbox],[type=radio],[readonly]):is(:active,:focus),:where(select,textarea):not([readonly]):is(:active,:focus){--pico-background-color: var(--pico-form-element-active-background-color)}input:not([type=submit],[type=button],[type=reset],[role=switch],[readonly]):is(:active,:focus),:where(select,textarea):not([readonly]):is(:active,:focus){--pico-border-color: var(--pico-form-element-active-border-color)}input:not([type=submit],[type=button],[type=reset],[type=range],[type=file],[readonly]):focus,:where(select,textarea):not([readonly]):focus{--pico-box-shadow: 0 0 0 var(--pico-outline-width) var(--pico-form-element-focus-color)}input:not([type=submit],[type=button],[type=reset])[disabled],select[disabled],textarea[disabled],label[aria-disabled=true],:where(fieldset[disabled]) :is(input:not([type=submit],[type=button],[type=reset]),select,textarea){opacity:var(--pico-form-element-disabled-opacity);pointer-events:none}label[aria-disabled=true] input[disabled]{opacity:1}:where(input,select,textarea):not([type=checkbox],[type=radio],[type=date],[type=datetime-local],[type=month],[type=time],[type=week],[type=range])[aria-invalid]{padding-right:calc(var(--pico-form-element-spacing-horizontal) + 1.5rem)!important;padding-left:var(--pico-form-element-spacing-horizontal);padding-inline-start:var(--pico-form-element-spacing-horizontal)!important;padding-inline-end:calc(var(--pico-form-element-spacing-horizontal) + 1.5rem)!important;background-position:center right .75rem;background-size:1rem auto;background-repeat:no-repeat}:where(input,select,textarea):not([type=checkbox],[type=radio],[type=date],[type=datetime-local],[type=month],[type=time],[type=week],[type=range])[aria-invalid=false]:not(select){background-image:var(--pico-icon-valid)}:where(input,select,textarea):not([type=checkbox],[type=radio],[type=date],[type=datetime-local],[type=month],[type=time],[type=week],[type=range])[aria-invalid=true]:not(select){background-image:var(--pico-icon-invalid)}:where(input,select,textarea)[aria-invalid=false]{--pico-border-color: var(--pico-form-element-valid-border-color)}:where(input,select,textarea)[aria-invalid=false]:is(:active,:focus){--pico-border-color: var(--pico-form-element-valid-active-border-color) !important}:where(input,select,textarea)[aria-invalid=false]:is(:active,:focus):not([type=checkbox],[type=radio]){--pico-box-shadow: 0 0 0 var(--pico-outline-width) var(--pico-form-element-valid-focus-color) !important}:where(input,select,textarea)[aria-invalid=true]{--pico-border-color: var(--pico-form-element-invalid-border-color)}:where(input,select,textarea)[aria-invalid=true]:is(:active,:focus){--pico-border-color: var(--pico-form-element-invalid-active-border-color) !important}:where(input,select,textarea)[aria-invalid=true]:is(:active,:focus):not([type=checkbox],[type=radio]){--pico-box-shadow: 0 0 0 var(--pico-outline-width) var(--pico-form-element-invalid-focus-color) !important}[dir=rtl] :where(input,select,textarea):not([type=checkbox],[type=radio]):is([aria-invalid],[aria-invalid=true],[aria-invalid=false]){background-position:center left .75rem}input::placeholder,input::-webkit-input-placeholder,textarea::placeholder,textarea::-webkit-input-placeholder,select:invalid{color:var(--pico-form-element-placeholder-color);opacity:1}input:not([type=checkbox],[type=radio]),select,textarea{margin-bottom:var(--pico-spacing)}select::-ms-expand{border:0;background-color:transparent}select:not([multiple],[size]){padding-right:calc(var(--pico-form-element-spacing-horizontal) + 1.5rem);padding-left:var(--pico-form-element-spacing-horizontal);padding-inline-start:var(--pico-form-element-spacing-horizontal);padding-inline-end:calc(var(--pico-form-element-spacing-horizontal) + 1.5rem);background-image:var(--pico-icon-chevron);background-position:center right .75rem;background-size:1rem auto;background-repeat:no-repeat}select[multiple] option:checked{background:var(--pico-form-element-selected-background-color);color:var(--pico-form-element-color)}[dir=rtl] select:not([multiple],[size]){background-position:center left .75rem}textarea{display:block;resize:vertical}textarea[aria-invalid]{--pico-icon-height: calc(1rem * var(--pico-line-height) + var(--pico-form-element-spacing-vertical) * 2 + var(--pico-border-width) * 2);background-position:top right .75rem!important;background-size:1rem var(--pico-icon-height)!important}:where(input,select,textarea,fieldset,.grid)+small{display:block;width:100%;margin-top:calc(var(--pico-spacing) * -.75);margin-bottom:var(--pico-spacing);color:var(--pico-muted-color)}:where(input,select,textarea,fieldset,.grid)[aria-invalid=false]+small{color:var(--pico-ins-color)}:where(input,select,textarea,fieldset,.grid)[aria-invalid=true]+small{color:var(--pico-del-color)}label>:where(input,select,textarea){margin-top:calc(var(--pico-spacing) * .25)}label:has([type=checkbox],[type=radio]){width:fit-content;cursor:pointer}[type=checkbox],[type=radio]{-webkit-appearance:none;-moz-appearance:none;appearance:none;width:1.25em;height:1.25em;margin-top:-.125em;margin-inline-end:.5em;border-width:var(--pico-border-width);vertical-align:middle;cursor:pointer}[type=checkbox]::-ms-check,[type=radio]::-ms-check{display:none}[type=checkbox]:checked,[type=checkbox]:checked:active,[type=checkbox]:checked:focus,[type=radio]:checked,[type=radio]:checked:active,[type=radio]:checked:focus{--pico-background-color: var(--pico-primary-background);--pico-border-color: var(--pico-primary-border);background-image:var(--pico-icon-checkbox);background-position:center;background-size:.75em auto;background-repeat:no-repeat}[type=checkbox]~label,[type=radio]~label{display:inline-block;margin-bottom:0;cursor:pointer}[type=checkbox]~label:not(:last-of-type),[type=radio]~label:not(:last-of-type){margin-inline-end:1em}[type=checkbox]:indeterminate{--pico-background-color: var(--pico-primary-background);--pico-border-color: var(--pico-primary-border);background-image:var(--pico-icon-minus);background-position:center;background-size:.75em auto;background-repeat:no-repeat}[type=radio]{border-radius:50%}[type=radio]:checked,[type=radio]:checked:active,[type=radio]:checked:focus{--pico-background-color: var(--pico-primary-inverse);border-width:.35em;background-image:none}[type=checkbox][role=switch]{--pico-background-color: var(--pico-switch-background-color);--pico-color: var(--pico-switch-color);width:2.25em;height:1.25em;border:var(--pico-border-width) solid var(--pico-border-color);border-radius:1.25em;background-color:var(--pico-background-color);line-height:1.25em}[type=checkbox][role=switch]:not([aria-invalid]){--pico-border-color: var(--pico-switch-background-color)}[type=checkbox][role=switch]:before{display:block;aspect-ratio:1;height:100%;border-radius:50%;background-color:var(--pico-color);box-shadow:var(--pico-switch-thumb-box-shadow);content:\"\";transition:margin .1s ease-in-out}[type=checkbox][role=switch]:focus{--pico-background-color: var(--pico-switch-background-color);--pico-border-color: var(--pico-switch-background-color)}[type=checkbox][role=switch]:checked{--pico-background-color: var(--pico-switch-checked-background-color);--pico-border-color: var(--pico-switch-checked-background-color);background-image:none}[type=checkbox][role=switch]:checked:before{margin-inline-start:1em}[type=checkbox][role=switch][disabled]{--pico-background-color: var(--pico-border-color)}[type=checkbox][aria-invalid=false]:checked,[type=checkbox][aria-invalid=false]:checked:active,[type=checkbox][aria-invalid=false]:checked:focus,[type=checkbox][role=switch][aria-invalid=false]:checked,[type=checkbox][role=switch][aria-invalid=false]:checked:active,[type=checkbox][role=switch][aria-invalid=false]:checked:focus{--pico-background-color: var(--pico-form-element-valid-border-color)}[type=checkbox]:checked[aria-invalid=true],[type=checkbox]:checked:active[aria-invalid=true],[type=checkbox]:checked:focus[aria-invalid=true],[type=checkbox][role=switch]:checked[aria-invalid=true],[type=checkbox][role=switch]:checked:active[aria-invalid=true],[type=checkbox][role=switch]:checked:focus[aria-invalid=true]{--pico-background-color: var(--pico-form-element-invalid-border-color)}[type=checkbox][aria-invalid=false]:checked,[type=checkbox][aria-invalid=false]:checked:active,[type=checkbox][aria-invalid=false]:checked:focus,[type=radio][aria-invalid=false]:checked,[type=radio][aria-invalid=false]:checked:active,[type=radio][aria-invalid=false]:checked:focus,[type=checkbox][role=switch][aria-invalid=false]:checked,[type=checkbox][role=switch][aria-invalid=false]:checked:active,[type=checkbox][role=switch][aria-invalid=false]:checked:focus{--pico-border-color: var(--pico-form-element-valid-border-color)}[type=checkbox]:checked[aria-invalid=true],[type=checkbox]:checked:active[aria-invalid=true],[type=checkbox]:checked:focus[aria-invalid=true],[type=radio]:checked[aria-invalid=true],[type=radio]:checked:active[aria-invalid=true],[type=radio]:checked:focus[aria-invalid=true],[type=checkbox][role=switch]:checked[aria-invalid=true],[type=checkbox][role=switch]:checked:active[aria-invalid=true],[type=checkbox][role=switch]:checked:focus[aria-invalid=true]{--pico-border-color: var(--pico-form-element-invalid-border-color)}[type=color]::-webkit-color-swatch-wrapper{padding:0}[type=color]::-moz-focus-inner{padding:0}[type=color]::-webkit-color-swatch{border:0;border-radius:calc(var(--pico-border-radius) * .5)}[type=color]::-moz-color-swatch{border:0;border-radius:calc(var(--pico-border-radius) * .5)}input:not([type=checkbox],[type=radio],[type=range],[type=file]):is([type=date],[type=datetime-local],[type=month],[type=time],[type=week]){--pico-icon-position: .75rem;--pico-icon-width: 1rem;padding-right:calc(var(--pico-icon-width) + var(--pico-icon-position));background-image:var(--pico-icon-date);background-position:center right var(--pico-icon-position);background-size:var(--pico-icon-width) auto;background-repeat:no-repeat}input:not([type=checkbox],[type=radio],[type=range],[type=file])[type=time]{background-image:var(--pico-icon-time)}[type=date]::-webkit-calendar-picker-indicator,[type=datetime-local]::-webkit-calendar-picker-indicator,[type=month]::-webkit-calendar-picker-indicator,[type=time]::-webkit-calendar-picker-indicator,[type=week]::-webkit-calendar-picker-indicator{width:var(--pico-icon-width);margin-right:calc(var(--pico-icon-width) * -1);margin-left:var(--pico-icon-position);opacity:0}@-moz-document url-prefix(){[type=date],[type=datetime-local],[type=month],[type=time],[type=week]{padding-right:var(--pico-form-element-spacing-horizontal)!important;background-image:none!important}}[dir=rtl] :is([type=date],[type=datetime-local],[type=month],[type=time],[type=week]){text-align:right}[type=file]{--pico-color: var(--pico-muted-color);margin-left:calc(var(--pico-outline-width) * -1);padding:calc(var(--pico-form-element-spacing-vertical) * .5) 0;padding-left:var(--pico-outline-width);border:0;border-radius:0;background:none}[type=file]::file-selector-button{margin-right:calc(var(--pico-spacing) / 2);padding:calc(var(--pico-form-element-spacing-vertical) * .5) var(--pico-form-element-spacing-horizontal)}[type=file]:is(:hover,:active,:focus)::file-selector-button{--pico-background-color: var(--pico-secondary-hover-background);--pico-border-color: var(--pico-secondary-hover-border)}[type=file]:focus::file-selector-button{--pico-box-shadow: var(--pico-button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)), 0 0 0 var(--pico-outline-width) var(--pico-secondary-focus)}[type=range]{-webkit-appearance:none;-moz-appearance:none;appearance:none;width:100%;height:1.25rem;background:none}[type=range]::-webkit-slider-runnable-track{width:100%;height:.375rem;border-radius:var(--pico-border-radius);background-color:var(--pico-range-border-color);transition:background-color var(--pico-transition),box-shadow var(--pico-transition)}[type=range]::-moz-range-track{width:100%;height:.375rem;border-radius:var(--pico-border-radius);background-color:var(--pico-range-border-color);transition:background-color var(--pico-transition),box-shadow var(--pico-transition)}[type=range]::-ms-track{width:100%;height:.375rem;border-radius:var(--pico-border-radius);background-color:var(--pico-range-border-color);transition:background-color var(--pico-transition),box-shadow var(--pico-transition)}[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:1.25rem;height:1.25rem;margin-top:-.4375rem;border:2px solid var(--pico-range-thumb-border-color);border-radius:50%;background-color:var(--pico-range-thumb-color);cursor:pointer;transition:background-color var(--pico-transition),transform var(--pico-transition)}[type=range]::-moz-range-thumb{-webkit-appearance:none;width:1.25rem;height:1.25rem;margin-top:-.4375rem;border:2px solid var(--pico-range-thumb-border-color);border-radius:50%;background-color:var(--pico-range-thumb-color);cursor:pointer;transition:background-color var(--pico-transition),transform var(--pico-transition)}[type=range]::-ms-thumb{-webkit-appearance:none;width:1.25rem;height:1.25rem;margin-top:-.4375rem;border:2px solid var(--pico-range-thumb-border-color);border-radius:50%;background-color:var(--pico-range-thumb-color);cursor:pointer;transition:background-color var(--pico-transition),transform var(--pico-transition)}[type=range]:active,[type=range]:focus-within{--pico-range-border-color: var(--pico-range-active-border-color);--pico-range-thumb-color: var(--pico-range-thumb-active-color)}[type=range]:active::-webkit-slider-thumb{transform:scale(1.25)}[type=range]:active::-moz-range-thumb{transform:scale(1.25)}[type=range]:active::-ms-thumb{transform:scale(1.25)}input:not([type=checkbox],[type=radio],[type=range],[type=file])[type=search]{padding-inline-start:calc(var(--pico-form-element-spacing-horizontal) + 1.75rem);background-image:var(--pico-icon-search);background-position:center left calc(var(--pico-form-element-spacing-horizontal) + .125rem);background-size:1rem auto;background-repeat:no-repeat}input:not([type=checkbox],[type=radio],[type=range],[type=file])[type=search][aria-invalid]{padding-inline-start:calc(var(--pico-form-element-spacing-horizontal) + 1.75rem)!important;background-position:center left 1.125rem,center right .75rem}input:not([type=checkbox],[type=radio],[type=range],[type=file])[type=search][aria-invalid=false]{background-image:var(--pico-icon-search),var(--pico-icon-valid)}input:not([type=checkbox],[type=radio],[type=range],[type=file])[type=search][aria-invalid=true]{background-image:var(--pico-icon-search),var(--pico-icon-invalid)}[dir=rtl] :where(input):not([type=checkbox],[type=radio],[type=range],[type=file])[type=search]{background-position:center right 1.125rem}[dir=rtl] :where(input):not([type=checkbox],[type=radio],[type=range],[type=file])[type=search][aria-invalid]{background-position:center right 1.125rem,center left .75rem}details{display:block;margin-bottom:var(--pico-spacing)}details summary{line-height:1rem;list-style-type:none;cursor:pointer;transition:color var(--pico-transition)}details summary:not([role]){color:var(--pico-accordion-close-summary-color)}details summary::-webkit-details-marker{display:none}details summary::marker{display:none}details summary::-moz-list-bullet{list-style-type:none}details summary:after{display:block;width:1rem;height:1rem;margin-inline-start:calc(var(--pico-spacing, 1rem) * .5);float:right;transform:rotate(-90deg);background-image:var(--pico-icon-chevron);background-position:right center;background-size:1rem auto;background-repeat:no-repeat;content:\"\";transition:transform var(--pico-transition)}details summary:focus{outline:none}details summary:focus:not([role]){color:var(--pico-accordion-active-summary-color)}details summary:focus-visible:not([role]){outline:var(--pico-outline-width) solid var(--pico-primary-focus);outline-offset:calc(var(--pico-spacing, 1rem) * .5);color:var(--pico-primary)}details summary[role=button]{width:100%;text-align:left}details summary[role=button]:after{height:calc(1rem * var(--pico-line-height, 1.5))}details[open]>summary{margin-bottom:var(--pico-spacing)}details[open]>summary:not([role]):not(:focus){color:var(--pico-accordion-open-summary-color)}details[open]>summary:after{transform:rotate(0)}[dir=rtl] details summary{text-align:right}[dir=rtl] details summary:after{float:left;background-position:left center}article{margin-bottom:var(--pico-block-spacing-vertical);padding:var(--pico-block-spacing-vertical) var(--pico-block-spacing-horizontal);border-radius:var(--pico-border-radius);background:var(--pico-card-background-color);box-shadow:var(--pico-card-box-shadow)}article>header,article>footer{margin-right:calc(var(--pico-block-spacing-horizontal) * -1);margin-left:calc(var(--pico-block-spacing-horizontal) * -1);padding:calc(var(--pico-block-spacing-vertical) * .66) var(--pico-block-spacing-horizontal);background-color:var(--pico-card-sectioning-background-color)}article>header{margin-top:calc(var(--pico-block-spacing-vertical) * -1);margin-bottom:var(--pico-block-spacing-vertical);border-bottom:var(--pico-border-width) solid var(--pico-card-border-color);border-top-right-radius:var(--pico-border-radius);border-top-left-radius:var(--pico-border-radius)}article>footer{margin-top:var(--pico-block-spacing-vertical);margin-bottom:calc(var(--pico-block-spacing-vertical) * -1);border-top:var(--pico-border-width) solid var(--pico-card-border-color);border-bottom-right-radius:var(--pico-border-radius);border-bottom-left-radius:var(--pico-border-radius)}details.dropdown{position:relative;border-bottom:none}details.dropdown>summary:after,details.dropdown>button:after,details.dropdown>a:after{display:block;width:1rem;height:calc(1rem * var(--pico-line-height, 1.5));margin-inline-start:.25rem;float:right;transform:rotate(0) translate(.2rem);background-image:var(--pico-icon-chevron);background-position:right center;background-size:1rem auto;background-repeat:no-repeat;content:\"\"}nav details.dropdown{margin-bottom:0}details.dropdown>summary:not([role]){height:calc(1rem * var(--pico-line-height) + var(--pico-form-element-spacing-vertical) * 2 + var(--pico-border-width) * 2);padding:var(--pico-form-element-spacing-vertical) var(--pico-form-element-spacing-horizontal);border:var(--pico-border-width) solid var(--pico-form-element-border-color);border-radius:var(--pico-border-radius);background-color:var(--pico-form-element-background-color);color:var(--pico-form-element-placeholder-color);line-height:inherit;cursor:pointer;-webkit-user-select:none;user-select:none;transition:background-color var(--pico-transition),border-color var(--pico-transition),color var(--pico-transition),box-shadow var(--pico-transition)}details.dropdown>summary:not([role]):active,details.dropdown>summary:not([role]):focus{border-color:var(--pico-form-element-active-border-color);background-color:var(--pico-form-element-active-background-color)}details.dropdown>summary:not([role]):focus{box-shadow:0 0 0 var(--pico-outline-width) var(--pico-form-element-focus-color)}details.dropdown>summary:not([role]):focus-visible{outline:none}details.dropdown>summary:not([role])[aria-invalid=false]{--pico-form-element-border-color: var(--pico-form-element-valid-border-color);--pico-form-element-active-border-color: var(--pico-form-element-valid-focus-color);--pico-form-element-focus-color: var(--pico-form-element-valid-focus-color)}details.dropdown>summary:not([role])[aria-invalid=true]{--pico-form-element-border-color: var(--pico-form-element-invalid-border-color);--pico-form-element-active-border-color: var(--pico-form-element-invalid-focus-color);--pico-form-element-focus-color: var(--pico-form-element-invalid-focus-color)}nav details.dropdown{display:inline;margin:calc(var(--pico-nav-element-spacing-vertical) * -1) 0}nav details.dropdown>summary:after{transform:rotate(0) translate(0)}nav details.dropdown>summary:not([role]){height:calc(1rem * var(--pico-line-height) + var(--pico-nav-link-spacing-vertical) * 2);padding:calc(var(--pico-nav-link-spacing-vertical) - var(--pico-border-width) * 2) var(--pico-nav-link-spacing-horizontal)}nav details.dropdown>summary:not([role]):focus-visible{box-shadow:0 0 0 var(--pico-outline-width) var(--pico-primary-focus)}details.dropdown>summary+ul{display:flex;z-index:99;position:absolute;left:0;flex-direction:column;width:100%;min-width:fit-content;margin:0;margin-top:var(--pico-outline-width);padding:0;border:var(--pico-border-width) solid var(--pico-dropdown-border-color);border-radius:var(--pico-border-radius);background-color:var(--pico-dropdown-background-color);box-shadow:var(--pico-dropdown-box-shadow);color:var(--pico-dropdown-color);white-space:nowrap;opacity:0;transition:opacity var(--pico-transition),transform 0s ease-in-out 1s}details.dropdown>summary+ul[dir=rtl]{right:0;left:auto}details.dropdown>summary+ul li{width:100%;margin-bottom:0;padding:calc(var(--pico-form-element-spacing-vertical) * .5) var(--pico-form-element-spacing-horizontal);list-style:none}details.dropdown>summary+ul li:first-of-type{margin-top:calc(var(--pico-form-element-spacing-vertical) * .5)}details.dropdown>summary+ul li:last-of-type{margin-bottom:calc(var(--pico-form-element-spacing-vertical) * .5)}details.dropdown>summary+ul li a{display:block;margin:calc(var(--pico-form-element-spacing-vertical) * -.5) calc(var(--pico-form-element-spacing-horizontal) * -1);padding:calc(var(--pico-form-element-spacing-vertical) * .5) var(--pico-form-element-spacing-horizontal);overflow:hidden;border-radius:0;color:var(--pico-dropdown-color);text-decoration:none;text-overflow:ellipsis}details.dropdown>summary+ul li a:hover,details.dropdown>summary+ul li a:focus,details.dropdown>summary+ul li a:active,details.dropdown>summary+ul li a:focus-visible,details.dropdown>summary+ul li a[aria-current]:not([aria-current=false]){background-color:var(--pico-dropdown-hover-background-color)}details.dropdown>summary+ul li label{width:100%}details.dropdown>summary+ul li:has(label):hover{background-color:var(--pico-dropdown-hover-background-color)}details.dropdown[open]>summary{margin-bottom:0}details.dropdown[open]>summary+ul{transform:scaleY(1);opacity:1;transition:opacity var(--pico-transition),transform 0s ease-in-out 0s}details.dropdown[open]>summary:before{display:block;z-index:1;position:fixed;width:100vw;height:100vh;inset:0;background:none;content:\"\";cursor:default}label>details.dropdown{margin-top:calc(var(--pico-spacing) * .25)}[role=search],[role=group]{display:inline-flex;position:relative;width:100%;margin-bottom:var(--pico-spacing);border-radius:var(--pico-border-radius);box-shadow:var(--pico-group-box-shadow, 0 0 0 rgba(0, 0, 0, 0));vertical-align:middle;transition:box-shadow var(--pico-transition)}[role=search]>*,[role=search] input:not([type=checkbox],[type=radio]),[role=search] select,[role=group]>*,[role=group] input:not([type=checkbox],[type=radio]),[role=group] select{position:relative;flex:1 1 auto;margin-bottom:0}[role=search]>*:not(:first-child),[role=search] input:not([type=checkbox],[type=radio]):not(:first-child),[role=search] select:not(:first-child),[role=group]>*:not(:first-child),[role=group] input:not([type=checkbox],[type=radio]):not(:first-child),[role=group] select:not(:first-child){margin-left:0;border-top-left-radius:0;border-bottom-left-radius:0}[role=search]>*:not(:last-child),[role=search] input:not([type=checkbox],[type=radio]):not(:last-child),[role=search] select:not(:last-child),[role=group]>*:not(:last-child),[role=group] input:not([type=checkbox],[type=radio]):not(:last-child),[role=group] select:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}[role=search]>*:focus,[role=search] input:not([type=checkbox],[type=radio]):focus,[role=search] select:focus,[role=group]>*:focus,[role=group] input:not([type=checkbox],[type=radio]):focus,[role=group] select:focus{z-index:2}[role=search] button:not(:first-child),[role=search] [type=submit]:not(:first-child),[role=search] [type=reset]:not(:first-child),[role=search] [type=button]:not(:first-child),[role=search] [role=button]:not(:first-child),[role=search] input:not([type=checkbox],[type=radio]):not(:first-child),[role=search] select:not(:first-child),[role=group] button:not(:first-child),[role=group] [type=submit]:not(:first-child),[role=group] [type=reset]:not(:first-child),[role=group] [type=button]:not(:first-child),[role=group] [role=button]:not(:first-child),[role=group] input:not([type=checkbox],[type=radio]):not(:first-child),[role=group] select:not(:first-child){margin-left:calc(var(--pico-border-width) * -1)}[role=search] button,[role=search] [type=submit],[role=search] [type=reset],[role=search] [type=button],[role=search] [role=button],[role=group] button,[role=group] [type=submit],[role=group] [type=reset],[role=group] [type=button],[role=group] [role=button]{width:auto}@supports selector(:has(*)){[role=search]:has(button:focus,[type=submit]:focus,[type=button]:focus,[role=button]:focus),[role=group]:has(button:focus,[type=submit]:focus,[type=button]:focus,[role=button]:focus){--pico-group-box-shadow: var(--pico-group-box-shadow-focus-with-button)}[role=search]:has(button:focus,[type=submit]:focus,[type=button]:focus,[role=button]:focus) input:not([type=checkbox],[type=radio]),[role=search]:has(button:focus,[type=submit]:focus,[type=button]:focus,[role=button]:focus) select,[role=group]:has(button:focus,[type=submit]:focus,[type=button]:focus,[role=button]:focus) input:not([type=checkbox],[type=radio]),[role=group]:has(button:focus,[type=submit]:focus,[type=button]:focus,[role=button]:focus) select{border-color:transparent}[role=search]:has(input:not([type=submit],[type=button]):focus,select:focus),[role=group]:has(input:not([type=submit],[type=button]):focus,select:focus){--pico-group-box-shadow: var(--pico-group-box-shadow-focus-with-input)}[role=search]:has(input:not([type=submit],[type=button]):focus,select:focus) button,[role=search]:has(input:not([type=submit],[type=button]):focus,select:focus) [type=submit],[role=search]:has(input:not([type=submit],[type=button]):focus,select:focus) [type=button],[role=search]:has(input:not([type=submit],[type=button]):focus,select:focus) [role=button],[role=group]:has(input:not([type=submit],[type=button]):focus,select:focus) button,[role=group]:has(input:not([type=submit],[type=button]):focus,select:focus) [type=submit],[role=group]:has(input:not([type=submit],[type=button]):focus,select:focus) [type=button],[role=group]:has(input:not([type=submit],[type=button]):focus,select:focus) [role=button]{--pico-button-box-shadow: 0 0 0 var(--pico-border-width) var(--pico-primary-border);--pico-button-hover-box-shadow: 0 0 0 var(--pico-border-width) var(--pico-primary-hover-border)}[role=search] button:focus,[role=search] [type=submit]:focus,[role=search] [type=reset]:focus,[role=search] [type=button]:focus,[role=search] [role=button]:focus,[role=group] button:focus,[role=group] [type=submit]:focus,[role=group] [type=reset]:focus,[role=group] [type=button]:focus,[role=group] [role=button]:focus{box-shadow:none}}[role=search]>*:first-child{border-top-left-radius:5rem;border-bottom-left-radius:5rem}[role=search]>*:last-child{border-top-right-radius:5rem;border-bottom-right-radius:5rem}[aria-busy=true]:not(input,select,textarea,html,form){white-space:nowrap}[aria-busy=true]:not(input,select,textarea,html,form):before{display:inline-block;width:1em;height:1em;background-image:var(--pico-icon-loading);background-size:1em auto;background-repeat:no-repeat;content:\"\";vertical-align:-.125em}[aria-busy=true]:not(input,select,textarea,html,form):not(:empty):before{margin-inline-end:calc(var(--pico-spacing) * .5)}[aria-busy=true]:not(input,select,textarea,html,form):empty{text-align:center}button[aria-busy=true],[type=submit][aria-busy=true],[type=button][aria-busy=true],[type=reset][aria-busy=true],[role=button][aria-busy=true],a[aria-busy=true]{pointer-events:none}:root,:host{--pico-scrollbar-width: 0px}dialog{display:flex;z-index:999;position:fixed;inset:0;align-items:center;justify-content:center;width:inherit;min-width:100%;height:inherit;min-height:100%;padding:0;border:0;-webkit-backdrop-filter:var(--pico-modal-overlay-backdrop-filter);backdrop-filter:var(--pico-modal-overlay-backdrop-filter);background-color:var(--pico-modal-overlay-background-color);color:var(--pico-color)}dialog>article{width:100%;max-height:calc(100vh - var(--pico-spacing) * 2);margin:var(--pico-spacing);overflow:auto}@media (min-width: 576px){dialog>article{max-width:510px}}@media (min-width: 768px){dialog>article{max-width:700px}}dialog>article>header>*{margin-bottom:0}dialog>article>header .close,dialog>article>header :is(a,button)[rel=prev]{margin:0;margin-left:var(--pico-spacing);padding:0;float:right}dialog>article>footer{text-align:right}dialog>article>footer button,dialog>article>footer [role=button]{margin-bottom:0}dialog>article>footer button:not(:first-of-type),dialog>article>footer [role=button]:not(:first-of-type){margin-left:calc(var(--pico-spacing) * .5)}dialog>article .close,dialog>article :is(a,button)[rel=prev]{display:block;width:1rem;height:1rem;margin-top:calc(var(--pico-spacing) * -1);margin-bottom:var(--pico-spacing);margin-left:auto;border:none;background-image:var(--pico-icon-close);background-position:center;background-size:auto 1rem;background-repeat:no-repeat;background-color:transparent;opacity:.5;transition:opacity var(--pico-transition)}dialog>article .close:is([aria-current]:not([aria-current=false]),:hover,:active,:focus),dialog>article :is(a,button)[rel=prev]:is([aria-current]:not([aria-current=false]),:hover,:active,:focus){opacity:1}dialog:not([open]),dialog[open=false]{display:none}.modal-is-open{padding-right:var(--pico-scrollbar-width, 0px);overflow:hidden;pointer-events:none;touch-action:none}.modal-is-open dialog{pointer-events:auto;touch-action:auto}:where(.modal-is-opening,.modal-is-closing) dialog,:where(.modal-is-opening,.modal-is-closing) dialog>article{animation-duration:.2s;animation-timing-function:ease-in-out;animation-fill-mode:both}:where(.modal-is-opening,.modal-is-closing) dialog{animation-duration:.8s;animation-name:modal-overlay}:where(.modal-is-opening,.modal-is-closing) dialog>article{animation-delay:.2s;animation-name:modal}.modal-is-closing dialog,.modal-is-closing dialog>article{animation-delay:0s;animation-direction:reverse}@keyframes modal-overlay{0%{-webkit-backdrop-filter:none;backdrop-filter:none;background-color:transparent}}@keyframes modal{0%{transform:translateY(-100%);opacity:0}}:where(nav li):before{float:left;content:\"\\200b\"}nav,nav ul{display:flex}nav{justify-content:space-between;overflow:visible}nav ol,nav ul{align-items:center;margin-bottom:0;padding:0;list-style:none}nav ol:first-of-type,nav ul:first-of-type{margin-left:calc(var(--pico-nav-element-spacing-horizontal) * -1)}nav ol:last-of-type,nav ul:last-of-type{margin-right:calc(var(--pico-nav-element-spacing-horizontal) * -1)}nav li{display:inline-block;margin:0;padding:var(--pico-nav-element-spacing-vertical) var(--pico-nav-element-spacing-horizontal)}nav li :where(a,[role=link]){display:inline-block;margin:calc(var(--pico-nav-link-spacing-vertical) * -1) calc(var(--pico-nav-link-spacing-horizontal) * -1);padding:var(--pico-nav-link-spacing-vertical) var(--pico-nav-link-spacing-horizontal);border-radius:var(--pico-border-radius)}nav li :where(a,[role=link]):not(:hover){text-decoration:none}nav li button,nav li [role=button],nav li [type=button],nav li input:not([type=checkbox],[type=radio],[type=range],[type=file]),nav li select{height:auto;margin-right:inherit;margin-bottom:0;margin-left:inherit;padding:calc(var(--pico-nav-link-spacing-vertical) - var(--pico-border-width) * 2) var(--pico-nav-link-spacing-horizontal)}nav[aria-label=breadcrumb]{align-items:center;justify-content:start}nav[aria-label=breadcrumb] ul li:not(:first-child){margin-inline-start:var(--pico-nav-link-spacing-horizontal)}nav[aria-label=breadcrumb] ul li a{margin:calc(var(--pico-nav-link-spacing-vertical) * -1) 0;margin-inline-start:calc(var(--pico-nav-link-spacing-horizontal) * -1)}nav[aria-label=breadcrumb] ul li:not(:last-child):after{display:inline-block;position:absolute;width:calc(var(--pico-nav-link-spacing-horizontal) * 4);margin:0 calc(var(--pico-nav-link-spacing-horizontal) * -1);content:var(--pico-nav-breadcrumb-divider);color:var(--pico-muted-color);text-align:center;text-decoration:none;white-space:nowrap}nav[aria-label=breadcrumb] a[aria-current]:not([aria-current=false]){background-color:transparent;color:inherit;text-decoration:none;pointer-events:none}aside nav,aside ol,aside ul,aside li{display:block}aside li{padding:calc(var(--pico-nav-element-spacing-vertical) * .5) var(--pico-nav-element-spacing-horizontal)}aside li a{display:block}aside li [role=button]{margin:inherit}[dir=rtl] nav[aria-label=breadcrumb] ul li:not(:last-child) :after{content:\"\\\\\"}progress{display:inline-block;vertical-align:baseline}progress{-webkit-appearance:none;-moz-appearance:none;display:inline-block;appearance:none;width:100%;height:.5rem;margin-bottom:calc(var(--pico-spacing) * .5);overflow:hidden;border:0;border-radius:var(--pico-border-radius);background-color:var(--pico-progress-background-color);color:var(--pico-progress-color)}progress::-webkit-progress-bar{border-radius:var(--pico-border-radius);background:none}progress[value]::-webkit-progress-value{background-color:var(--pico-progress-color);transition:inline-size var(--pico-transition)}progress::-moz-progress-bar{background-color:var(--pico-progress-color)}@media (prefers-reduced-motion: no-preference){progress:indeterminate{background:var(--pico-progress-background-color) linear-gradient(to right,var(--pico-progress-color) 30%,var(--pico-progress-background-color) 30%) top left/150% 150% no-repeat;animation:progress-indeterminate 1s linear infinite}progress:indeterminate[value]::-webkit-progress-value{background-color:transparent}progress:indeterminate::-moz-progress-bar{background-color:transparent}}@media (prefers-reduced-motion: no-preference){[dir=rtl] progress:indeterminate{animation-direction:reverse}}@keyframes progress-indeterminate{0%{background-position:200% 0}to{background-position:-200% 0}}[data-tooltip]{position:relative}[data-tooltip]:not(a,button,input,[role=button]){border-bottom:1px dotted;text-decoration:none;cursor:help}[data-tooltip][data-placement=top]:before,[data-tooltip][data-placement=top]:after,[data-tooltip]:before,[data-tooltip]:after{display:block;z-index:99;position:absolute;bottom:100%;left:50%;padding:.25rem .5rem;overflow:hidden;transform:translate(-50%,-.25rem);border-radius:var(--pico-border-radius);background:var(--pico-tooltip-background-color);content:attr(data-tooltip);color:var(--pico-tooltip-color);font-style:normal;font-weight:var(--pico-font-weight);font-size:.875rem;text-decoration:none;text-overflow:ellipsis;white-space:nowrap;opacity:0;pointer-events:none}[data-tooltip][data-placement=top]:after,[data-tooltip]:after{padding:0;transform:translate(-50%);border-top:.3rem solid;border-right:.3rem solid transparent;border-left:.3rem solid transparent;border-radius:0;background-color:transparent;content:\"\";color:var(--pico-tooltip-background-color)}[data-tooltip][data-placement=bottom]:before,[data-tooltip][data-placement=bottom]:after{top:100%;bottom:auto;transform:translate(-50%,.25rem)}[data-tooltip][data-placement=bottom]:after{transform:translate(-50%,-.3rem);border:.3rem solid transparent;border-bottom:.3rem solid}[data-tooltip][data-placement=left]:before,[data-tooltip][data-placement=left]:after{inset:50% 100% auto auto;transform:translate(-.25rem,-50%)}[data-tooltip][data-placement=left]:after{transform:translate(.3rem,-50%);border:.3rem solid transparent;border-left:.3rem solid}[data-tooltip][data-placement=right]:before,[data-tooltip][data-placement=right]:after{inset:50% auto auto 100%;transform:translate(.25rem,-50%)}[data-tooltip][data-placement=right]:after{transform:translate(-.3rem,-50%);border:.3rem solid transparent;border-right:.3rem solid}[data-tooltip]:focus:before,[data-tooltip]:focus:after,[data-tooltip]:hover:before,[data-tooltip]:hover:after{opacity:1}@media (hover: hover) and (pointer: fine){[data-tooltip]:focus:before,[data-tooltip]:focus:after,[data-tooltip]:hover:before,[data-tooltip]:hover:after{--pico-tooltip-slide-to: translate(-50%, -.25rem);transform:translate(-50%,.75rem);animation-duration:.2s;animation-fill-mode:forwards;animation-name:tooltip-slide;opacity:0}[data-tooltip]:focus:after,[data-tooltip]:hover:after{--pico-tooltip-caret-slide-to: translate(-50%, 0rem);transform:translate(-50%,-.25rem);animation-name:tooltip-caret-slide}[data-tooltip][data-placement=bottom]:focus:before,[data-tooltip][data-placement=bottom]:focus:after,[data-tooltip][data-placement=bottom]:hover:before,[data-tooltip][data-placement=bottom]:hover:after{--pico-tooltip-slide-to: translate(-50%, .25rem);transform:translate(-50%,-.75rem);animation-name:tooltip-slide}[data-tooltip][data-placement=bottom]:focus:after,[data-tooltip][data-placement=bottom]:hover:after{--pico-tooltip-caret-slide-to: translate(-50%, -.3rem);transform:translate(-50%,-.5rem);animation-name:tooltip-caret-slide}[data-tooltip][data-placement=left]:focus:before,[data-tooltip][data-placement=left]:focus:after,[data-tooltip][data-placement=left]:hover:before,[data-tooltip][data-placement=left]:hover:after{--pico-tooltip-slide-to: translate(-.25rem, -50%);transform:translate(.75rem,-50%);animation-name:tooltip-slide}[data-tooltip][data-placement=left]:focus:after,[data-tooltip][data-placement=left]:hover:after{--pico-tooltip-caret-slide-to: translate(.3rem, -50%);transform:translate(.05rem,-50%);animation-name:tooltip-caret-slide}[data-tooltip][data-placement=right]:focus:before,[data-tooltip][data-placement=right]:focus:after,[data-tooltip][data-placement=right]:hover:before,[data-tooltip][data-placement=right]:hover:after{--pico-tooltip-slide-to: translate(.25rem, -50%);transform:translate(-.75rem,-50%);animation-name:tooltip-slide}[data-tooltip][data-placement=right]:focus:after,[data-tooltip][data-placement=right]:hover:after{--pico-tooltip-caret-slide-to: translate(-.3rem, -50%);transform:translate(-.05rem,-50%);animation-name:tooltip-caret-slide}}@keyframes tooltip-slide{to{transform:var(--pico-tooltip-slide-to);opacity:1}}@keyframes tooltip-caret-slide{50%{opacity:0}to{transform:var(--pico-tooltip-caret-slide-to);opacity:1}}[aria-controls]{cursor:pointer}[aria-disabled=true],[disabled]{cursor:not-allowed}[aria-hidden=false][hidden]{display:initial}[aria-hidden=false][hidden]:not(:focus){clip:rect(0,0,0,0);position:absolute}a,area,button,input,label,select,summary,textarea,[tabindex]{-ms-touch-action:manipulation}[dir=rtl]{direction:rtl}@media (prefers-reduced-motion: reduce){*:not([aria-busy=true]),:not([aria-busy=true]):before,:not([aria-busy=true]):after{background-attachment:initial!important;animation-duration:1ms!important;animation-delay:-1ms!important;animation-iteration-count:1!important;scroll-behavior:auto!important;transition-delay:0s!important;transition-duration:0s!important}}:host{display:block;background-color:var(--pico-background-color);height:100%;width:100%}fieldset legend{font-weight:700}.toolbar-container{padding:4px;height:100%;display:flex;justify-content:center}.toolbar-container .button-container{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px}.toolbar-container .buttons-divider{border-top:1px solid var(--pico-secondary);margin:1rem 0;width:100%}.toolbar-container.horizontal{width:100%}.toolbar-container.horizontal .button-container{flex-direction:row}.toolbar-container.horizontal .buttons-divider{border-left:1px solid var(--pico-secondary);height:100%;margin:0 1rem;width:0}.toolbar-position-buttons{display:flex;gap:4px}.toolbar-position-buttons button{flex-grow:1}.power-buttons button{display:block;width:100%}.settings-toolbar-dock{margin-top:1rem}\n/*!\n * Pico CSS \u2728 v2.1.1 (https://picocss.com)\n * Copyright 2019-2025 - Licensed under MIT\n */\n"] }]
|
|
258
|
+
}] });
|
|
259
|
+
|
|
260
|
+
// ===BEGIN LICENSE===
|
|
261
|
+
// Copyright 2025 Carnegie Mellon University. All rights reserved.
|
|
262
|
+
// Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
|
|
263
|
+
// ===END LICENSE===
|
|
264
|
+
class ConsoleForgeConfig {
|
|
265
|
+
}
|
|
266
|
+
const defaultCfConfig = {
|
|
267
|
+
canvasRecording: {
|
|
268
|
+
chunkLength: 1000,
|
|
269
|
+
frameRate: 25,
|
|
270
|
+
maxDuration: 10000,
|
|
271
|
+
mimeType: "video/webm"
|
|
272
|
+
},
|
|
273
|
+
consoleBackgroundStyle: "rgb(40, 40, 40)",
|
|
274
|
+
consoleToolbarComponent: ConsoleToolbarDefaultComponent,
|
|
275
|
+
enableClipboard: true,
|
|
276
|
+
enableConsoleRecord: true,
|
|
277
|
+
logThreshold: LogLevel.WARNING,
|
|
278
|
+
showBrowserNotificationsOnConsoleEvents: true,
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Extracts plain text from a ClipboardItem, if available.
|
|
283
|
+
*
|
|
284
|
+
* @param clipboardItem - The ClipboardItem to extract text from.
|
|
285
|
+
* @returns A promise that resolves to the extracted text, or null if no text is present.
|
|
286
|
+
*
|
|
287
|
+
* @example
|
|
288
|
+
* const text = await getTextFromClipboardItem(item);
|
|
289
|
+
* if (text) {
|
|
290
|
+
* console.log("Clipboard text:", text);
|
|
291
|
+
* }
|
|
292
|
+
*/
|
|
293
|
+
async function getTextFromClipboardItem(clipboardItem) {
|
|
294
|
+
const textMimeType = "text/plain";
|
|
295
|
+
if (!clipboardItem?.types?.includes(textMimeType)) {
|
|
296
|
+
return null;
|
|
297
|
+
}
|
|
298
|
+
const blob = await clipboardItem.getType(textMimeType);
|
|
299
|
+
if (!blob) {
|
|
300
|
+
return null;
|
|
301
|
+
}
|
|
302
|
+
return blob.text();
|
|
303
|
+
}
|
|
304
|
+
function getClipboardItemFromText(text) {
|
|
305
|
+
return new ClipboardItem({ 'text/plain': new Blob([text], { type: 'text/plain' }) });
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// ===BEGIN LICENSE===
|
|
309
|
+
// Copyright 2025 Carnegie Mellon University. All rights reserved.
|
|
310
|
+
// Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
|
|
311
|
+
// ===END LICENSE===
|
|
312
|
+
class ClipboardService {
|
|
313
|
+
cfConfig = inject(ConsoleForgeConfig);
|
|
314
|
+
document = inject(DOCUMENT);
|
|
315
|
+
userSettings = inject(UserSettingsService);
|
|
316
|
+
_localClipboardContentWritten = signal(undefined);
|
|
317
|
+
localClipboardContentWritten = this._localClipboardContentWritten.asReadonly();
|
|
318
|
+
copyBlob(blob) {
|
|
319
|
+
return this.writeToClipboard(new ClipboardItem({ [blob.type]: blob }));
|
|
320
|
+
}
|
|
321
|
+
copyText(text) {
|
|
322
|
+
return this.writeToClipboard(getClipboardItemFromText(text));
|
|
323
|
+
}
|
|
324
|
+
async readText() {
|
|
325
|
+
const clipboard = this.getClipboard();
|
|
326
|
+
if (!clipboard) {
|
|
327
|
+
throw new Error("Can't access the clipboard to read text");
|
|
328
|
+
}
|
|
329
|
+
return clipboard.readText();
|
|
330
|
+
}
|
|
331
|
+
getClipboard() {
|
|
332
|
+
if (!this.cfConfig.enableClipboard) {
|
|
333
|
+
throw new Error("ConsoleForge's clipboard access has been disabled.");
|
|
334
|
+
}
|
|
335
|
+
return this.document?.defaultView?.navigator?.clipboard;
|
|
336
|
+
}
|
|
337
|
+
writeToClipboard(item) {
|
|
338
|
+
const clipboard = this.getClipboard();
|
|
339
|
+
if (!clipboard) {
|
|
340
|
+
throw new Error("Can't access the clipboard to write content");
|
|
341
|
+
}
|
|
342
|
+
if (!this.userSettings.settings().console.allowCopyToLocalClipboard) {
|
|
343
|
+
throw new Error("User has disabled ConsoleForge's access to their local clipboard.");
|
|
344
|
+
}
|
|
345
|
+
clipboard.write([item]);
|
|
346
|
+
this._localClipboardContentWritten.update(() => item);
|
|
347
|
+
}
|
|
348
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ClipboardService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
349
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ClipboardService, providedIn: 'root' });
|
|
350
|
+
}
|
|
351
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ClipboardService, decorators: [{
|
|
352
|
+
type: Injectable,
|
|
353
|
+
args: [{ providedIn: 'root' }]
|
|
354
|
+
}] });
|
|
355
|
+
|
|
356
|
+
// ===BEGIN LICENSE===
|
|
357
|
+
// Copyright 2025 Carnegie Mellon University. All rights reserved.
|
|
358
|
+
// Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
|
|
359
|
+
// ===END LICENSE===
|
|
360
|
+
class VncConsoleClientService {
|
|
361
|
+
_consoleClipboardUpdated = signal("");
|
|
362
|
+
consoleClipboardUpdated = this._consoleClipboardUpdated.asReadonly();
|
|
363
|
+
_connectionStatus = signal("disconnected");
|
|
364
|
+
connectionStatus = this._connectionStatus.asReadonly();
|
|
365
|
+
_supportedFeatures = signal({
|
|
366
|
+
onScreenKeyboard: false,
|
|
367
|
+
powerManagement: false
|
|
368
|
+
});
|
|
369
|
+
supportedFeatures = this._supportedFeatures.asReadonly();
|
|
370
|
+
// injected services
|
|
371
|
+
cfConfig = inject(ConsoleForgeConfig);
|
|
372
|
+
clipboardService = inject(ClipboardService);
|
|
373
|
+
logger = inject(LoggerService);
|
|
374
|
+
userSettings = inject(UserSettingsService);
|
|
375
|
+
// the actual client from @novnc/novnc
|
|
376
|
+
noVncClient;
|
|
377
|
+
async connect(url, options) {
|
|
378
|
+
if (this.noVncClient) {
|
|
379
|
+
this.noVncClient.disconnect();
|
|
380
|
+
}
|
|
381
|
+
return new Promise((resolve, reject) => {
|
|
382
|
+
try {
|
|
383
|
+
this._connectionStatus.update(() => "connecting");
|
|
384
|
+
this.logger.log(LogLevel.DEBUG, "Connecting to", url);
|
|
385
|
+
let client = new NoVncClient(options.hostElement, url, {
|
|
386
|
+
credentials: {
|
|
387
|
+
password: options?.credentials?.accessTicket || options?.credentials?.password || "",
|
|
388
|
+
// explicitly not supporting these for now
|
|
389
|
+
username: "",
|
|
390
|
+
target: ""
|
|
391
|
+
}
|
|
392
|
+
});
|
|
393
|
+
client = this.doPreConnectionConfig(client);
|
|
394
|
+
client.addEventListener("connect", () => {
|
|
395
|
+
// do other post-connection config
|
|
396
|
+
this.noVncClient = this.doPostConnectionConfig(client, options);
|
|
397
|
+
// the vnc client knows its capabilities post-connection
|
|
398
|
+
// so send this back along with the things we know we can't support
|
|
399
|
+
const supportedFeatures = {
|
|
400
|
+
onScreenKeyboard: false,
|
|
401
|
+
powerManagement: this.noVncClient.capabilities.power,
|
|
402
|
+
};
|
|
403
|
+
this._supportedFeatures.update(() => supportedFeatures);
|
|
404
|
+
this.noVncClient = client;
|
|
405
|
+
resolve(supportedFeatures);
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
catch (err) {
|
|
409
|
+
this._connectionStatus.update(() => "disconnected");
|
|
410
|
+
reject(err);
|
|
411
|
+
}
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
async disconnect() {
|
|
415
|
+
this.logger.log(LogLevel.DEBUG, "Manual disconnection requested");
|
|
416
|
+
return this.handleDisconnect(true);
|
|
417
|
+
}
|
|
418
|
+
dispose() {
|
|
419
|
+
return this.disconnect();
|
|
420
|
+
}
|
|
421
|
+
async copyVmClipboard() {
|
|
422
|
+
throw new Error("Unsupported over VNC");
|
|
423
|
+
}
|
|
424
|
+
async sendClipboardText(text) {
|
|
425
|
+
if (!this.noVncClient) {
|
|
426
|
+
throw new Error("VNC client isn't connected; can't send clipboard text.");
|
|
427
|
+
}
|
|
428
|
+
this.noVncClient.clipboardPasteFrom(text);
|
|
429
|
+
this._consoleClipboardUpdated.update(() => text);
|
|
430
|
+
}
|
|
431
|
+
async sendCtrlAltDelete() {
|
|
432
|
+
if (!this.noVncClient) {
|
|
433
|
+
throw new Error("VNC client isn't connected; can't send CtrlAltDelete.");
|
|
434
|
+
}
|
|
435
|
+
this.noVncClient.sendCtrlAltDel();
|
|
436
|
+
}
|
|
437
|
+
async sendPowerRequest(request) {
|
|
438
|
+
if (!this.noVncClient) {
|
|
439
|
+
throw new Error(`VNC client isn't connected; can't send power request "${request}"`);
|
|
440
|
+
}
|
|
441
|
+
if (!this.noVncClient.capabilities.power) {
|
|
442
|
+
throw new Error(`The machine you're connected to over VNC doesn't have the "power" capability, so reboots, resets, and shutdowns aren't permitted.`);
|
|
443
|
+
}
|
|
444
|
+
switch (request) {
|
|
445
|
+
case "reboot":
|
|
446
|
+
this.noVncClient.machineReboot();
|
|
447
|
+
return;
|
|
448
|
+
case "rebootHard":
|
|
449
|
+
this.noVncClient.machineReset();
|
|
450
|
+
return;
|
|
451
|
+
case "shutdown":
|
|
452
|
+
this.noVncClient.machineShutdown();
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
async setIsViewOnly(isViewOnly) {
|
|
457
|
+
if (!this.noVncClient) {
|
|
458
|
+
throw new Error("VNC client isn't connected; can't set properties");
|
|
459
|
+
}
|
|
460
|
+
this.noVncClient.viewOnly = isViewOnly;
|
|
461
|
+
}
|
|
462
|
+
async setPreserveAspectRatioOnScale(preserve) {
|
|
463
|
+
if (!this.noVncClient) {
|
|
464
|
+
throw new Error("VNC client isn't connected; can't set properties");
|
|
465
|
+
}
|
|
466
|
+
this.logger.log(LogLevel.DEBUG, "Set preserve aspect ratio to", preserve);
|
|
467
|
+
this.noVncClient.scaleViewport = preserve;
|
|
468
|
+
}
|
|
469
|
+
doPreConnectionConfig(client) {
|
|
470
|
+
client.addEventListener("connect", () => this._connectionStatus.update(() => "connected"));
|
|
471
|
+
client.addEventListener("disconnect", ev => this.handleDisconnect(ev.detail.clean));
|
|
472
|
+
client.addEventListener("clipboard", ev => {
|
|
473
|
+
if (!this.cfConfig.enableClipboard) {
|
|
474
|
+
this.logger.log(LogLevel.INFO, "The remote console tried to copy text to the local clipboard, but local clipboard access is disabled in ConsoleForge's configuration.");
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
const currentUserSettings = this.userSettings.settings();
|
|
478
|
+
if (!currentUserSettings.console.allowCopyToLocalClipboard) {
|
|
479
|
+
this.logger.log(LogLevel.INFO, "The remote console tried to copy text to the local clipboard, but you've disabled local clipboard copy. Use ConsoleForge's settings to allow it to copy text to your local clipboard.");
|
|
480
|
+
return;
|
|
481
|
+
}
|
|
482
|
+
if (ev.detail.text) {
|
|
483
|
+
this.clipboardService.copyText(ev.detail.text);
|
|
484
|
+
}
|
|
485
|
+
});
|
|
486
|
+
return client;
|
|
487
|
+
}
|
|
488
|
+
doPostConnectionConfig(client, options) {
|
|
489
|
+
client.background = options.backgroundStyle || "";
|
|
490
|
+
client.resizeSession = true;
|
|
491
|
+
// try focus if requested
|
|
492
|
+
if (options.autoFocusOnConnect) {
|
|
493
|
+
client.focus();
|
|
494
|
+
}
|
|
495
|
+
return client;
|
|
496
|
+
}
|
|
497
|
+
handleDisconnect(isManualDisconnect) {
|
|
498
|
+
this._connectionStatus.update(() => "disconnected");
|
|
499
|
+
if (!isManualDisconnect) {
|
|
500
|
+
this.logger.log(LogLevel.WARNING, "Unexpected disconnection");
|
|
501
|
+
}
|
|
502
|
+
if (this.noVncClient) {
|
|
503
|
+
this.noVncClient.disconnect();
|
|
504
|
+
this.noVncClient = undefined;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: VncConsoleClientService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
508
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: VncConsoleClientService, providedIn: 'root' });
|
|
509
|
+
}
|
|
510
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: VncConsoleClientService, decorators: [{
|
|
511
|
+
type: Injectable,
|
|
512
|
+
args: [{ providedIn: 'root' }]
|
|
513
|
+
}] });
|
|
514
|
+
|
|
515
|
+
// ===BEGIN LICENSE===
|
|
516
|
+
// Copyright 2025 Carnegie Mellon University. All rights reserved.
|
|
517
|
+
// Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
|
|
518
|
+
// ===END LICENSE===
|
|
519
|
+
function resolveWMKSLib() {
|
|
520
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
521
|
+
return window.WMKS;
|
|
522
|
+
}
|
|
523
|
+
function createWmksClient(hostElementId, options) {
|
|
524
|
+
const result = resolveWMKSLib();
|
|
525
|
+
return result.createWMKS(hostElementId, options);
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
// ===BEGIN LICENSE===
|
|
529
|
+
// Copyright 2025 Carnegie Mellon University. All rights reserved.
|
|
530
|
+
// Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
|
|
531
|
+
// ===END LICENSE===
|
|
532
|
+
var WmksAudioEncodingType;
|
|
533
|
+
(function (WmksAudioEncodingType) {
|
|
534
|
+
WmksAudioEncodingType["AAC"] = "aac";
|
|
535
|
+
WmksAudioEncodingType["OPUS"] = "opus";
|
|
536
|
+
WmksAudioEncodingType["VORBIS"] = "vorbis";
|
|
537
|
+
})(WmksAudioEncodingType || (WmksAudioEncodingType = {}));
|
|
538
|
+
var WmksConnectionState;
|
|
539
|
+
(function (WmksConnectionState) {
|
|
540
|
+
WmksConnectionState["CONNECTED"] = "connected";
|
|
541
|
+
WmksConnectionState["CONNECTING"] = "connecting";
|
|
542
|
+
WmksConnectionState["DISCONNECTED"] = "disconnected";
|
|
543
|
+
})(WmksConnectionState || (WmksConnectionState = {}));
|
|
544
|
+
var WmksErrorType;
|
|
545
|
+
(function (WmksErrorType) {
|
|
546
|
+
WmksErrorType["AUTHENTICATION_FAILED"] = "authenticationfailed";
|
|
547
|
+
WmksErrorType["PROTOCOL_ERROR"] = "protocolerror";
|
|
548
|
+
WmksErrorType["WEBSOCKET_ERROR"] = "websocketerror";
|
|
549
|
+
})(WmksErrorType || (WmksErrorType = {}));
|
|
550
|
+
var WmksEvents;
|
|
551
|
+
(function (WmksEvents) {
|
|
552
|
+
WmksEvents["AUDIO"] = "audio";
|
|
553
|
+
WmksEvents["CONNECTION_STATE_CHANGE"] = "connectionstatechange";
|
|
554
|
+
WmksEvents["COPY"] = "copy";
|
|
555
|
+
WmksEvents["ERROR"] = "error";
|
|
556
|
+
WmksEvents["FULL_SCREEN_CHANGE"] = "fullscreenchange";
|
|
557
|
+
WmksEvents["HEARTBEAT"] = "heartbeat";
|
|
558
|
+
WmksEvents["KEYBOARD_LEDS_CHANGE"] = "keyboardledschanged";
|
|
559
|
+
WmksEvents["REMOTE_SCREEN_SIZE_CHANGE"] = "screensizechange";
|
|
560
|
+
WmksEvents["TOGGLE"] = "toggle";
|
|
561
|
+
})(WmksEvents || (WmksEvents = {}));
|
|
562
|
+
var WmksPosition;
|
|
563
|
+
(function (WmksPosition) {
|
|
564
|
+
WmksPosition[WmksPosition["CENTER"] = 0] = "CENTER";
|
|
565
|
+
WmksPosition[WmksPosition["LEFT_TOP"] = 1] = "LEFT_TOP";
|
|
566
|
+
})(WmksPosition || (WmksPosition = {}));
|
|
567
|
+
|
|
568
|
+
// ===BEGIN LICENSE===
|
|
569
|
+
// Copyright 2025 Carnegie Mellon University. All rights reserved.
|
|
570
|
+
// Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
|
|
571
|
+
// ===END LICENSE===
|
|
572
|
+
class VmWareConsoleClientService {
|
|
573
|
+
cfConfig = inject(ConsoleForgeConfig);
|
|
574
|
+
clipboardService = inject(ClipboardService);
|
|
575
|
+
logger = inject(LoggerService);
|
|
576
|
+
document = inject(DOCUMENT);
|
|
577
|
+
window = inject(WINDOW);
|
|
578
|
+
wmksClient;
|
|
579
|
+
_connectionStatus = signal("disconnected");
|
|
580
|
+
connectionStatus = this._connectionStatus.asReadonly();
|
|
581
|
+
_consoleClipboardUpdated = signal("");
|
|
582
|
+
consoleClipboardUpdated = this._consoleClipboardUpdated.asReadonly();
|
|
583
|
+
_supportedFeatures = signal({ onScreenKeyboard: true, powerManagement: false });
|
|
584
|
+
supportedFeatures = this._supportedFeatures.asReadonly();
|
|
585
|
+
_needsCanvasSizeUpdate = new Subject();
|
|
586
|
+
_needsCanvasSizeUpdateSub = this._needsCanvasSizeUpdate.pipe(debounceTime(250), takeUntilDestroyed()).subscribe(() => {
|
|
587
|
+
if (this.wmksClient) {
|
|
588
|
+
this.logger.log(LogLevel.DEBUG, "Document size change, updating canvas");
|
|
589
|
+
if (this.wmksClient && this.wmksClient.getConnectionState() == "connected") {
|
|
590
|
+
this.wmksClient.updateScreen();
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
});
|
|
594
|
+
connect(url, options) {
|
|
595
|
+
if (!options.hostElement) {
|
|
596
|
+
throw new Error("A host element is required to connect to a VMWare WMKS console.");
|
|
597
|
+
}
|
|
598
|
+
return new Promise((resolve, reject) => {
|
|
599
|
+
this.wmksClient = createWmksClient(options.hostElement.id, {
|
|
600
|
+
changeResolution: true,
|
|
601
|
+
rescale: true,
|
|
602
|
+
useNativePixels: true,
|
|
603
|
+
useVNCHandshake: false,
|
|
604
|
+
position: WmksPosition.CENTER
|
|
605
|
+
})
|
|
606
|
+
.register(WmksEvents.CONNECTION_STATE_CHANGE, (ev, data) => {
|
|
607
|
+
this.logger.log(LogLevel.DEBUG, "WMKS state change", ev, data);
|
|
608
|
+
if (data.state === WmksConnectionState.DISCONNECTED) {
|
|
609
|
+
this._connectionStatus.update(() => "disconnected");
|
|
610
|
+
this.doPostDisconnectionConfig();
|
|
611
|
+
reject();
|
|
612
|
+
}
|
|
613
|
+
if (data.state === WmksConnectionState.CONNECTED) {
|
|
614
|
+
this.logger.log(LogLevel.DEBUG, "WMKS confirms connection", this.wmksClient);
|
|
615
|
+
this.doPostConnectionConfig(options.hostElement);
|
|
616
|
+
this._connectionStatus.update(() => "connected");
|
|
617
|
+
resolve({
|
|
618
|
+
onScreenKeyboard: true,
|
|
619
|
+
powerManagement: false
|
|
620
|
+
});
|
|
621
|
+
}
|
|
622
|
+
})
|
|
623
|
+
.register(WmksEvents.COPY, (ev, data) => {
|
|
624
|
+
this.logger.log(LogLevel.DEBUG, "Clipboard data available", ev, data);
|
|
625
|
+
if (this.cfConfig.enableClipboard) {
|
|
626
|
+
this.clipboardService.copyText(data);
|
|
627
|
+
}
|
|
628
|
+
})
|
|
629
|
+
.register(WmksEvents.ERROR, (ev, data) => {
|
|
630
|
+
this.logger.log(LogLevel.ERROR, "Error from WMKS:", ev, data);
|
|
631
|
+
})
|
|
632
|
+
// as far as i can tell, this never happens
|
|
633
|
+
.register(WmksEvents.HEARTBEAT, (ev, data) => this.logger.log(LogLevel.DEBUG, "WMKS heartbeat", ev, data))
|
|
634
|
+
.register(WmksEvents.REMOTE_SCREEN_SIZE_CHANGE, (ev, data) => {
|
|
635
|
+
if (!this.wmksClient) {
|
|
636
|
+
return;
|
|
637
|
+
}
|
|
638
|
+
this.logger.log(LogLevel.DEBUG, "Remote screen size change", ev, data);
|
|
639
|
+
this.wmksClient.updateScreen();
|
|
640
|
+
})
|
|
641
|
+
.register(WmksEvents.TOGGLE, (ev, data) => {
|
|
642
|
+
this.logger.log(LogLevel.DEBUG, "Visible devices toggle", ev, data);
|
|
643
|
+
});
|
|
644
|
+
this.wmksClient.connect(url);
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
disconnect() {
|
|
648
|
+
if (this.wmksClient) {
|
|
649
|
+
this.wmksClient.disconnect();
|
|
650
|
+
this.wmksClient = undefined;
|
|
651
|
+
}
|
|
652
|
+
return Promise.resolve();
|
|
653
|
+
}
|
|
654
|
+
async copyVmClipboard() {
|
|
655
|
+
if (!this.wmksClient || this.wmksClient.getConnectionState() !== "connected") {
|
|
656
|
+
throw new Error("WMKS not connected; can't copy clipboard content");
|
|
657
|
+
}
|
|
658
|
+
// The "got clipboard data" event only fires when the VM canvas loses focus for some godforsaken reason,
|
|
659
|
+
// so you have to manually blur it to get the event to fire
|
|
660
|
+
// https://techdocs.broadcom.com/us/en/vmware-cis/vsphere/vsphere-sdks-tools/8-0/html-console-sdk-programming-guide/handling-events-with-the-html-console/copy-from-remote-desktop.html
|
|
661
|
+
// this.wmksClient.grab();
|
|
662
|
+
// this.wmksClient.ungrab();
|
|
663
|
+
}
|
|
664
|
+
async sendClipboardText(text) {
|
|
665
|
+
if (!this.wmksClient) {
|
|
666
|
+
throw new Error("Can't resolve WMKS client; can't send clipboard text.");
|
|
667
|
+
}
|
|
668
|
+
const lines = text.trim().split("\n");
|
|
669
|
+
if (lines.length === 1) {
|
|
670
|
+
this.wmksClient.sendInputString(lines[0]);
|
|
671
|
+
}
|
|
672
|
+
else {
|
|
673
|
+
for (const line of text.split("\n")) {
|
|
674
|
+
this.wmksClient.sendInputString(`${line}\n`);
|
|
675
|
+
await new Promise(r => setTimeout(r, 40));
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
sendCtrlAltDelete() {
|
|
680
|
+
return new Promise((resolve, reject) => {
|
|
681
|
+
try {
|
|
682
|
+
if (!this.wmksClient) {
|
|
683
|
+
throw new Error("Couldn't resolve client; can't send Ctrl+Alt+Del");
|
|
684
|
+
}
|
|
685
|
+
this.wmksClient.sendCAD();
|
|
686
|
+
resolve();
|
|
687
|
+
}
|
|
688
|
+
catch (err) {
|
|
689
|
+
reject(err);
|
|
690
|
+
}
|
|
691
|
+
});
|
|
692
|
+
}
|
|
693
|
+
sendPowerRequest(request) {
|
|
694
|
+
return Promise.reject(`Power management request aren't supported for VMWare consoles. (rejected request: "${request}")`);
|
|
695
|
+
}
|
|
696
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
697
|
+
setIsViewOnly(isViewOnly) {
|
|
698
|
+
console.warn("NYI");
|
|
699
|
+
return Promise.resolve();
|
|
700
|
+
}
|
|
701
|
+
setPreserveAspectRatioOnScale(scaleToContainerSize) {
|
|
702
|
+
return new Promise((resolve, reject) => {
|
|
703
|
+
try {
|
|
704
|
+
if (!this.wmksClient) {
|
|
705
|
+
throw new Error("Couldn't resolve client; can't set option");
|
|
706
|
+
}
|
|
707
|
+
this.wmksClient.setOption("rescale", scaleToContainerSize);
|
|
708
|
+
resolve();
|
|
709
|
+
}
|
|
710
|
+
catch (err) {
|
|
711
|
+
reject(err);
|
|
712
|
+
}
|
|
713
|
+
});
|
|
714
|
+
}
|
|
715
|
+
dispose() {
|
|
716
|
+
if (this.wmksClient) {
|
|
717
|
+
this.wmksClient.destroy();
|
|
718
|
+
this.wmksClient = undefined;
|
|
719
|
+
}
|
|
720
|
+
return Promise.resolve();
|
|
721
|
+
}
|
|
722
|
+
doPostConnectionConfig(hostElement) {
|
|
723
|
+
if (!this.document) {
|
|
724
|
+
this.logger.log(LogLevel.WARNING, "Couldn't resolve the document for host event listening.");
|
|
725
|
+
}
|
|
726
|
+
this.document.addEventListener("fullscreenchange", this.handleWindowSizeChange.bind(this));
|
|
727
|
+
this.document.addEventListener("resize", this.handleWindowSizeChange.bind(this));
|
|
728
|
+
if (!this.window) {
|
|
729
|
+
this.logger.log(LogLevel.WARNING, "Couldn't resolve the window for host event listening.");
|
|
730
|
+
}
|
|
731
|
+
this.window.addEventListener("resize", this.handleWindowSizeChange.bind(this));
|
|
732
|
+
// also listen for canvas events i guess because it matters or something i hate everything
|
|
733
|
+
const canvas = hostElement.querySelector("canvas");
|
|
734
|
+
if (canvas) {
|
|
735
|
+
canvas.addEventListener("blur", () => {
|
|
736
|
+
if (this.wmksClient) {
|
|
737
|
+
this.wmksClient.ungrab();
|
|
738
|
+
}
|
|
739
|
+
});
|
|
740
|
+
canvas.addEventListener("focus", () => {
|
|
741
|
+
if (this.wmksClient) {
|
|
742
|
+
this.wmksClient.grab();
|
|
743
|
+
}
|
|
744
|
+
});
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
doPostDisconnectionConfig() {
|
|
748
|
+
this.document.removeEventListener("fullscreenchange", this.handleWindowSizeChange.bind(this));
|
|
749
|
+
this.document.removeEventListener("resize", this.handleWindowSizeChange.bind(this));
|
|
750
|
+
}
|
|
751
|
+
handleWindowSizeChange() {
|
|
752
|
+
this._needsCanvasSizeUpdate.next();
|
|
753
|
+
}
|
|
754
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: VmWareConsoleClientService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
755
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: VmWareConsoleClientService, providedIn: 'root' });
|
|
756
|
+
}
|
|
757
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: VmWareConsoleClientService, decorators: [{
|
|
758
|
+
type: Injectable,
|
|
759
|
+
args: [{ providedIn: 'root' }]
|
|
760
|
+
}] });
|
|
761
|
+
|
|
762
|
+
// ===BEGIN LICENSE===
|
|
763
|
+
// Copyright 2025 Carnegie Mellon University. All rights reserved.
|
|
764
|
+
// Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
|
|
765
|
+
// ===END LICENSE===
|
|
766
|
+
class ConsoleClientFactoryService {
|
|
767
|
+
injector = inject(Injector);
|
|
768
|
+
get(consoleClientType) {
|
|
769
|
+
switch (consoleClientType) {
|
|
770
|
+
case "vmware": {
|
|
771
|
+
const client = this.injector.get(VmWareConsoleClientService);
|
|
772
|
+
if (!client) {
|
|
773
|
+
throw new Error(`Couldn't resolve instance from injector token ${VmWareConsoleClientService}`);
|
|
774
|
+
}
|
|
775
|
+
return client;
|
|
776
|
+
}
|
|
777
|
+
case "vnc": {
|
|
778
|
+
const client = this.injector.get(VncConsoleClientService);
|
|
779
|
+
if (!client) {
|
|
780
|
+
throw new Error(`Couldn't resolve instance from injector token ${VncConsoleClientService}`);
|
|
781
|
+
}
|
|
782
|
+
return client;
|
|
783
|
+
}
|
|
784
|
+
default:
|
|
785
|
+
throw new Error(`Console type ${consoleClientType} NYI`);
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConsoleClientFactoryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
789
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConsoleClientFactoryService, providedIn: 'root' });
|
|
790
|
+
}
|
|
791
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConsoleClientFactoryService, decorators: [{
|
|
792
|
+
type: Injectable,
|
|
793
|
+
args: [{ providedIn: 'root' }]
|
|
794
|
+
}] });
|
|
795
|
+
|
|
796
|
+
// ===BEGIN LICENSE===
|
|
797
|
+
// Copyright 2025 Carnegie Mellon University. All rights reserved.
|
|
798
|
+
// Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
|
|
799
|
+
// ===END LICENSE===
|
|
800
|
+
class UuidService {
|
|
801
|
+
get() {
|
|
802
|
+
if (!crypto) {
|
|
803
|
+
throw new Error("Failed to generate UUID: Can't resolve the `crypto` dependency in this environment.");
|
|
804
|
+
}
|
|
805
|
+
return crypto.randomUUID();
|
|
806
|
+
}
|
|
807
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: UuidService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
808
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: UuidService, providedIn: 'root' });
|
|
809
|
+
}
|
|
810
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: UuidService, decorators: [{
|
|
811
|
+
type: Injectable,
|
|
812
|
+
args: [{ providedIn: 'root' }]
|
|
813
|
+
}] });
|
|
814
|
+
|
|
815
|
+
// ===BEGIN LICENSE===
|
|
816
|
+
// Copyright 2025 Carnegie Mellon University. All rights reserved.
|
|
817
|
+
// Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
|
|
818
|
+
// ===END LICENSE===
|
|
819
|
+
class FullScreenService {
|
|
820
|
+
doc = inject(DOCUMENT);
|
|
821
|
+
_isAvailable = signal(this.doc.fullscreenEnabled);
|
|
822
|
+
isAvailable = this._isAvailable.asReadonly();
|
|
823
|
+
constructor() {
|
|
824
|
+
this.doc.addEventListener("fullscreenchange", () => {
|
|
825
|
+
this._isAvailable.update(() => this.doc.fullscreenEnabled && !this.doc.fullscreenElement);
|
|
826
|
+
});
|
|
827
|
+
this.doc.addEventListener("fullscreenerror", () => {
|
|
828
|
+
this._isAvailable.update(() => this.doc.fullscreenEnabled && !this.doc.fullscreenElement);
|
|
829
|
+
});
|
|
830
|
+
}
|
|
831
|
+
async exitFullscreen() {
|
|
832
|
+
return this.doc.exitFullscreen();
|
|
833
|
+
}
|
|
834
|
+
async tryFullscreen(element) {
|
|
835
|
+
return element.requestFullscreen({ navigationUI: "hide" });
|
|
836
|
+
}
|
|
837
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: FullScreenService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
838
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: FullScreenService, providedIn: 'root' });
|
|
839
|
+
}
|
|
840
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: FullScreenService, decorators: [{
|
|
841
|
+
type: Injectable,
|
|
842
|
+
args: [{ providedIn: 'root' }]
|
|
843
|
+
}], ctorParameters: () => [] });
|
|
844
|
+
|
|
845
|
+
// ===BEGIN LICENSE===
|
|
846
|
+
// Copyright 2025 Carnegie Mellon University. All rights reserved.
|
|
847
|
+
// Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
|
|
848
|
+
// ===END LICENSE===
|
|
849
|
+
class CanvasRecording {
|
|
850
|
+
chunks = [];
|
|
851
|
+
mimeType;
|
|
852
|
+
recorder;
|
|
853
|
+
window;
|
|
854
|
+
autostopTimeoutRef;
|
|
855
|
+
// Stopping is a bit tricky.
|
|
856
|
+
//
|
|
857
|
+
// The MediaRecorder doesn't guarantee the validity of the emitted blob until `onstop` is fired. This means that when someone
|
|
858
|
+
// calls in to stop the recording, we need to create a (deferred) promise that `.onstop` can resolve when it fires successfully.
|
|
859
|
+
//
|
|
860
|
+
//
|
|
861
|
+
// We store the promise at the class level, because we should only ever have one of them (set when .stop` is called). But we also
|
|
862
|
+
// store the "resolve" call here, because its value is set in `.stop` but consumed in the `.onstop` event of the recorder.
|
|
863
|
+
stopPromise;
|
|
864
|
+
stopResolveFn;
|
|
865
|
+
settings;
|
|
866
|
+
constructor(settings) {
|
|
867
|
+
this.settings = settings;
|
|
868
|
+
this.mimeType = settings.mimeType;
|
|
869
|
+
this.recorder = new MediaRecorder(settings.stream, { mimeType: settings.mimeType });
|
|
870
|
+
this.window = settings.window;
|
|
871
|
+
// pipe the output of the recorder into the local chunks array
|
|
872
|
+
this.recorder.ondataavailable = ev => this.chunks.push(ev.data);
|
|
873
|
+
this.recorder.onerror = (ev) => {
|
|
874
|
+
throw (ev.error);
|
|
875
|
+
};
|
|
876
|
+
this.recorder.onstop = () => {
|
|
877
|
+
// the "resolve" is set at the class level by the `.stop` method for access here
|
|
878
|
+
if (this.stopResolveFn) {
|
|
879
|
+
const blob = new Blob(this.chunks, { type: this.mimeType });
|
|
880
|
+
this.stopResolveFn(blob);
|
|
881
|
+
this.stopResolveFn = undefined;
|
|
882
|
+
// the settings have an OnStop callback that should be invoked so
|
|
883
|
+
// the service constructing these things can know if any are going on
|
|
884
|
+
this.settings.onStopCallback();
|
|
885
|
+
}
|
|
886
|
+
};
|
|
887
|
+
this.recorder.start(settings.chunkLength);
|
|
888
|
+
this.autostopTimeoutRef = window.setTimeout(() => this.stop(), settings.maxDuration);
|
|
889
|
+
}
|
|
890
|
+
stop() {
|
|
891
|
+
if (this.stopPromise) {
|
|
892
|
+
// if defined, stop's already been called, so we
|
|
893
|
+
// want to give back the same promise
|
|
894
|
+
return this.stopPromise;
|
|
895
|
+
}
|
|
896
|
+
// clear the autotimeout if it's been set for this
|
|
897
|
+
if (this.autostopTimeoutRef) {
|
|
898
|
+
this.window.clearTimeout(this.autostopTimeoutRef);
|
|
899
|
+
this.autostopTimeoutRef = undefined;
|
|
900
|
+
}
|
|
901
|
+
// record the stop promise we're about to send back, so we can return it to
|
|
902
|
+
// anyone who calls .stop again by mistake
|
|
903
|
+
this.stopPromise = new Promise(resolve => this.stopResolveFn = resolve);
|
|
904
|
+
// stop the recorder and return
|
|
905
|
+
this.recorder.stop();
|
|
906
|
+
return this.stopPromise;
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
// ===BEGIN LICENSE===
|
|
911
|
+
// Copyright 2025 Carnegie Mellon University. All rights reserved.
|
|
912
|
+
// Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
|
|
913
|
+
// ===END LICENSE===
|
|
914
|
+
class CanvasRecorderService {
|
|
915
|
+
cfConfig = inject(ConsoleForgeConfig);
|
|
916
|
+
uuids = inject(UuidService);
|
|
917
|
+
window = inject(WINDOW);
|
|
918
|
+
activeRecordings = new Set();
|
|
919
|
+
_isRecording = signal(false);
|
|
920
|
+
isRecording = this._isRecording.asReadonly();
|
|
921
|
+
startRecord(canvas) {
|
|
922
|
+
if (!this.cfConfig.enableConsoleRecord) {
|
|
923
|
+
throw new Error("Console recording has been disabled in ConsoleForge.");
|
|
924
|
+
}
|
|
925
|
+
const recording = new CanvasRecording({
|
|
926
|
+
id: this.uuids.get(),
|
|
927
|
+
stream: canvas.captureStream(this.cfConfig.canvasRecording.frameRate || 25),
|
|
928
|
+
window: this.window,
|
|
929
|
+
chunkLength: this.cfConfig.canvasRecording.chunkLength || 1000,
|
|
930
|
+
maxDuration: this.cfConfig.canvasRecording.maxDuration || 60000,
|
|
931
|
+
mimeType: this.cfConfig.canvasRecording.mimeType || "video/webm",
|
|
932
|
+
onStopCallback: () => this.recordingStopped(recording)
|
|
933
|
+
});
|
|
934
|
+
this.activeRecordings.add(recording);
|
|
935
|
+
this._isRecording.set(true);
|
|
936
|
+
return recording;
|
|
937
|
+
}
|
|
938
|
+
recordingStopped(recording) {
|
|
939
|
+
this.activeRecordings.delete(recording);
|
|
940
|
+
this._isRecording.set(this.activeRecordings.size > 0);
|
|
941
|
+
}
|
|
942
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: CanvasRecorderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
943
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: CanvasRecorderService, providedIn: 'root' });
|
|
944
|
+
}
|
|
945
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: CanvasRecorderService, decorators: [{
|
|
946
|
+
type: Injectable,
|
|
947
|
+
args: [{ providedIn: 'root' }]
|
|
948
|
+
}] });
|
|
949
|
+
|
|
950
|
+
// EXPLICITLY not provided in root - this is provided by ConsoleComponent,
|
|
951
|
+
// and each should get its own
|
|
952
|
+
class CanvasService {
|
|
953
|
+
_canvas = signal(null);
|
|
954
|
+
canvas = this._canvas.asReadonly();
|
|
955
|
+
clearCanvas() {
|
|
956
|
+
this._canvas.update(() => null);
|
|
957
|
+
}
|
|
958
|
+
setCanvas(canvas) {
|
|
959
|
+
this._canvas.update(() => canvas);
|
|
960
|
+
}
|
|
961
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: CanvasService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
962
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: CanvasService });
|
|
963
|
+
}
|
|
964
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: CanvasService, decorators: [{
|
|
965
|
+
type: Injectable
|
|
966
|
+
}] });
|
|
967
|
+
|
|
968
|
+
// ===BEGIN LICENSE===
|
|
969
|
+
// Copyright 2025 Carnegie Mellon University. All rights reserved.
|
|
970
|
+
// Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
|
|
971
|
+
// ===END LICENSE===
|
|
972
|
+
class ConsoleToolbarComponent {
|
|
973
|
+
consoleClient = input.required();
|
|
974
|
+
consoleNetworkConfig = input();
|
|
975
|
+
customToolbarComponent = input();
|
|
976
|
+
canvasRecordingStarted = output();
|
|
977
|
+
canvasRecordingFinished = output();
|
|
978
|
+
ctrlAltDelSent = output();
|
|
979
|
+
networkConnectionRequested = output();
|
|
980
|
+
networkDisconnectRequested = output();
|
|
981
|
+
powerRequestSent = output();
|
|
982
|
+
screenshotCopied = output();
|
|
983
|
+
toggleFullscreen = output();
|
|
984
|
+
canvas = inject(CanvasService);
|
|
985
|
+
canvasRecorder = inject(CanvasRecorderService);
|
|
986
|
+
clipboardService = inject(ClipboardService);
|
|
987
|
+
config = inject(ConsoleForgeConfig);
|
|
988
|
+
logger = inject(LoggerService);
|
|
989
|
+
userSettings = inject(UserSettingsService);
|
|
990
|
+
// component state
|
|
991
|
+
activeConsoleRecording = signal(undefined);
|
|
992
|
+
toolbarComponentContext;
|
|
993
|
+
toolbarComponent = computed(() => this.customToolbarComponent() || this.config.consoleToolbarComponent);
|
|
994
|
+
constructor() {
|
|
995
|
+
this.toolbarComponentContext = {
|
|
996
|
+
console: {
|
|
997
|
+
copyScreenshot: this.handleCopyScreenshot.bind(this),
|
|
998
|
+
recordScreenStart: this.handleRecordScreenStart.bind(this),
|
|
999
|
+
recordScreenStop: this.handleRecordScreenStop.bind(this),
|
|
1000
|
+
sendCtrlAltDel: this.handleSendCtrlAltDelete.bind(this),
|
|
1001
|
+
sendPowerRequest: this.handleSendPowerRequest.bind(this),
|
|
1002
|
+
sendTextToClipboard: this.handleSendTextToClipboard.bind(this),
|
|
1003
|
+
supportedFeatures: computed(() => this.consoleClient().supportedFeatures()),
|
|
1004
|
+
toggleFullscreen: this.handleFullscreen.bind(this)
|
|
1005
|
+
},
|
|
1006
|
+
networks: {
|
|
1007
|
+
config: this.consoleNetworkConfig,
|
|
1008
|
+
connectionRequested: this.handleNetworkConnectionRequest.bind(this),
|
|
1009
|
+
disconnectRequested: () => this.networkDisconnectRequested.emit(),
|
|
1010
|
+
},
|
|
1011
|
+
state: {
|
|
1012
|
+
activeConsoleRecording: computed(() => this.activeConsoleRecording()),
|
|
1013
|
+
isConnected: computed(() => this.consoleClient() && this.consoleClient().connectionStatus() === "connected"),
|
|
1014
|
+
isFullscreenAvailable: inject(FullScreenService).isAvailable,
|
|
1015
|
+
isRecordingAvailable: computed(() => !!this.canvas.canvas())
|
|
1016
|
+
},
|
|
1017
|
+
userSettings: this.userSettings
|
|
1018
|
+
};
|
|
1019
|
+
}
|
|
1020
|
+
async handleCopyScreenshot() {
|
|
1021
|
+
if (!this.canvas.canvas()) {
|
|
1022
|
+
throw new Error("Couldn't resolve the canvas; can't copy screenshot.");
|
|
1023
|
+
}
|
|
1024
|
+
this.canvas.canvas().toBlob(blob => {
|
|
1025
|
+
if (!blob) {
|
|
1026
|
+
throw new Error("Couldn't resolve canvas blob.");
|
|
1027
|
+
}
|
|
1028
|
+
this.clipboardService.copyBlob(blob);
|
|
1029
|
+
this.screenshotCopied.emit(blob);
|
|
1030
|
+
});
|
|
1031
|
+
}
|
|
1032
|
+
handleFullscreen() {
|
|
1033
|
+
this.toggleFullscreen.emit();
|
|
1034
|
+
return Promise.resolve();
|
|
1035
|
+
}
|
|
1036
|
+
handleNetworkConnectionRequest(networkName) {
|
|
1037
|
+
const availableNetworks = this.consoleNetworkConfig()?.available || [];
|
|
1038
|
+
if (availableNetworks.indexOf(networkName) === -1) {
|
|
1039
|
+
throw new Error(`Network ${networkName} is not available to this console.`);
|
|
1040
|
+
}
|
|
1041
|
+
this.networkConnectionRequested.emit(networkName);
|
|
1042
|
+
}
|
|
1043
|
+
handleRecordScreenStart() {
|
|
1044
|
+
if (!this.canvas.canvas()) {
|
|
1045
|
+
throw new Error("Can't resolve canvas for recording");
|
|
1046
|
+
}
|
|
1047
|
+
this.logger.log(LogLevel.DEBUG, "Recording canvas", this.canvas.canvas());
|
|
1048
|
+
const recordingInstance = this.canvasRecorder.startRecord(this.canvas.canvas());
|
|
1049
|
+
this.activeConsoleRecording.update(() => recordingInstance);
|
|
1050
|
+
this.canvasRecordingStarted.emit();
|
|
1051
|
+
}
|
|
1052
|
+
async handleRecordScreenStop() {
|
|
1053
|
+
if (!this.activeConsoleRecording()) {
|
|
1054
|
+
throw new Error("There is no active console recording - unable to stop and emit recorded data.");
|
|
1055
|
+
}
|
|
1056
|
+
this.logger.log(LogLevel.DEBUG, "Recording stopped.");
|
|
1057
|
+
const recording = await this.activeConsoleRecording().stop();
|
|
1058
|
+
this.activeConsoleRecording.update(() => undefined);
|
|
1059
|
+
this.canvasRecordingFinished.emit(recording);
|
|
1060
|
+
this.logger.log(LogLevel.DEBUG, "Recording emitted.");
|
|
1061
|
+
return recording;
|
|
1062
|
+
}
|
|
1063
|
+
handleSendCtrlAltDelete() {
|
|
1064
|
+
this.consoleClient().sendCtrlAltDelete();
|
|
1065
|
+
this.ctrlAltDelSent.emit();
|
|
1066
|
+
return Promise.resolve();
|
|
1067
|
+
}
|
|
1068
|
+
async handleSendPowerRequest(request) {
|
|
1069
|
+
this.consoleClient().sendPowerRequest(request);
|
|
1070
|
+
this.powerRequestSent.emit(request);
|
|
1071
|
+
return Promise.resolve();
|
|
1072
|
+
}
|
|
1073
|
+
async handleSendTextToClipboard(text) {
|
|
1074
|
+
if (text) {
|
|
1075
|
+
this.consoleClient().sendClipboardText(text);
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConsoleToolbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1079
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: ConsoleToolbarComponent, isStandalone: true, selector: "cf-console-toolbar", inputs: { consoleClient: { classPropertyName: "consoleClient", publicName: "consoleClient", isSignal: true, isRequired: true, transformFunction: null }, consoleNetworkConfig: { classPropertyName: "consoleNetworkConfig", publicName: "consoleNetworkConfig", isSignal: true, isRequired: false, transformFunction: null }, customToolbarComponent: { classPropertyName: "customToolbarComponent", publicName: "customToolbarComponent", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { canvasRecordingStarted: "canvasRecordingStarted", canvasRecordingFinished: "canvasRecordingFinished", ctrlAltDelSent: "ctrlAltDelSent", networkConnectionRequested: "networkConnectionRequested", networkDisconnectRequested: "networkDisconnectRequested", powerRequestSent: "powerRequestSent", screenshotCopied: "screenshotCopied", toggleFullscreen: "toggleFullscreen" }, ngImport: i0, template: "<!-- ===BEGIN LICENSE=== -->\n<!-- Copyright 2025 Carnegie Mellon University. All rights reserved. -->\n<!-- Released under an MIT (SEI)-style license. See the LICENSE.md file for license information. -->\n<!-- ===END LICENSE=== -->\n\n@if (toolbarComponent()) {\n<ng-container *ngComponentOutlet=\"toolbarComponent()!; inputs: { 'consoleContext': toolbarComponentContext }\" />\n}\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }] });
|
|
1080
|
+
}
|
|
1081
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConsoleToolbarComponent, decorators: [{
|
|
1082
|
+
type: Component,
|
|
1083
|
+
args: [{ selector: 'cf-console-toolbar', imports: [CommonModule], template: "<!-- ===BEGIN LICENSE=== -->\n<!-- Copyright 2025 Carnegie Mellon University. All rights reserved. -->\n<!-- Released under an MIT (SEI)-style license. See the LICENSE.md file for license information. -->\n<!-- ===END LICENSE=== -->\n\n@if (toolbarComponent()) {\n<ng-container *ngComponentOutlet=\"toolbarComponent()!; inputs: { 'consoleContext': toolbarComponentContext }\" />\n}\n" }]
|
|
1084
|
+
}], ctorParameters: () => [] });
|
|
1085
|
+
|
|
1086
|
+
// ===BEGIN LICENSE===
|
|
1087
|
+
// Copyright 2025 Carnegie Mellon University. All rights reserved.
|
|
1088
|
+
// Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
|
|
1089
|
+
// ===END LICENSE===
|
|
1090
|
+
class BrowserNotificationsService {
|
|
1091
|
+
config = inject(ConsoleForgeConfig);
|
|
1092
|
+
logger = inject(LoggerService);
|
|
1093
|
+
window = inject(WINDOW);
|
|
1094
|
+
async send(args) {
|
|
1095
|
+
if (!this.config.showBrowserNotificationsOnConsoleEvents) {
|
|
1096
|
+
return;
|
|
1097
|
+
}
|
|
1098
|
+
const hasBrowserPermission = await Notification.requestPermission();
|
|
1099
|
+
if (hasBrowserPermission == "denied") {
|
|
1100
|
+
this.logger.log(LogLevel.WARNING, "Can't send notification - browser permission denied.", args);
|
|
1101
|
+
}
|
|
1102
|
+
const notification = new Notification(args.title, {
|
|
1103
|
+
body: args.body,
|
|
1104
|
+
tag: args.tag,
|
|
1105
|
+
});
|
|
1106
|
+
if (args.href?.url) {
|
|
1107
|
+
notification.onclick = (ev) => {
|
|
1108
|
+
ev.preventDefault();
|
|
1109
|
+
this.window.open(args.href?.url, args.href?.target);
|
|
1110
|
+
};
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: BrowserNotificationsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1114
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: BrowserNotificationsService, providedIn: 'root' });
|
|
1115
|
+
}
|
|
1116
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: BrowserNotificationsService, decorators: [{
|
|
1117
|
+
type: Injectable,
|
|
1118
|
+
args: [{ providedIn: 'root' }]
|
|
1119
|
+
}] });
|
|
1120
|
+
|
|
1121
|
+
// ===BEGIN LICENSE===
|
|
1122
|
+
// Copyright 2025 Carnegie Mellon University. All rights reserved.
|
|
1123
|
+
// Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
|
|
1124
|
+
// ===END LICENSE===
|
|
1125
|
+
class ConsoleStatusComponent {
|
|
1126
|
+
status = input("disconnected");
|
|
1127
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConsoleStatusComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1128
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: ConsoleStatusComponent, isStandalone: true, selector: "cf-console-status", inputs: { status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<!-- ===BEGIN LICENSE=== -->\n<!-- Copyright 2025 Carnegie Mellon University. All rights reserved. -->\n<!-- Released under an MIT (SEI)-style license. See the LICENSE.md file for license information. -->\n<!-- ===END LICENSE=== -->\n\n@if (status() === \"connecting\") {\n<progress></progress>\n}\n@else if(!status() || status() == \"disconnected\") {\n<div class=\"disconnected-banner\">\n Console disconnected\n</div>\n}\n", styles: [".disconnected-banner{background-color:#d93526;color:var(--pico-color);font-weight:700;padding:4px 0;text-align:center}progress{width:100%}\n"] });
|
|
1129
|
+
}
|
|
1130
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConsoleStatusComponent, decorators: [{
|
|
1131
|
+
type: Component,
|
|
1132
|
+
args: [{ selector: 'cf-console-status', template: "<!-- ===BEGIN LICENSE=== -->\n<!-- Copyright 2025 Carnegie Mellon University. All rights reserved. -->\n<!-- Released under an MIT (SEI)-style license. See the LICENSE.md file for license information. -->\n<!-- ===END LICENSE=== -->\n\n@if (status() === \"connecting\") {\n<progress></progress>\n}\n@else if(!status() || status() == \"disconnected\") {\n<div class=\"disconnected-banner\">\n Console disconnected\n</div>\n}\n", styles: [".disconnected-banner{background-color:#d93526;color:var(--pico-color);font-weight:700;padding:4px 0;text-align:center}progress{width:100%}\n"] }]
|
|
1133
|
+
}] });
|
|
1134
|
+
|
|
1135
|
+
// ===BEGIN LICENSE===
|
|
1136
|
+
// Copyright 2025 Carnegie Mellon University. All rights reserved.
|
|
1137
|
+
// Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
|
|
1138
|
+
// ===END LICENSE===
|
|
1139
|
+
class ConsoleComponent {
|
|
1140
|
+
// component I/O
|
|
1141
|
+
autoConnect = input(true);
|
|
1142
|
+
config = input.required();
|
|
1143
|
+
isViewOnly = input(false);
|
|
1144
|
+
networkConfig = input();
|
|
1145
|
+
toolbarComponent = input();
|
|
1146
|
+
consoleClipboardUpdated = output();
|
|
1147
|
+
consoleRecorded = output();
|
|
1148
|
+
ctrlAltDelSent = output();
|
|
1149
|
+
localClipboardUpdated = output();
|
|
1150
|
+
networkConnectionRequested = output();
|
|
1151
|
+
networkDisconnectRequested = output();
|
|
1152
|
+
powerRequestSent = output();
|
|
1153
|
+
screenshotCopied = output();
|
|
1154
|
+
status = computed(() => this.consoleClient()?.connectionStatus() || "disconnected");
|
|
1155
|
+
// services
|
|
1156
|
+
browserNotifications = inject(BrowserNotificationsService);
|
|
1157
|
+
canvasService = inject(CanvasService);
|
|
1158
|
+
clipboardService = inject(ClipboardService);
|
|
1159
|
+
consoleClientFactory = inject(ConsoleClientFactoryService);
|
|
1160
|
+
consoleForgeConfig = inject(ConsoleForgeConfig);
|
|
1161
|
+
document = inject(DOCUMENT);
|
|
1162
|
+
fullscreen = inject(FullScreenService);
|
|
1163
|
+
logger = inject(LoggerService);
|
|
1164
|
+
userSettingsService = inject(UserSettingsService);
|
|
1165
|
+
uuids = inject(UuidService);
|
|
1166
|
+
// viewkids
|
|
1167
|
+
componentContainer = viewChild.required("componentContainer");
|
|
1168
|
+
consoleHostElement = viewChild.required("consoleHost");
|
|
1169
|
+
// other component state
|
|
1170
|
+
consoleClient = signal(undefined);
|
|
1171
|
+
consoleHostElementId = `cf-console-${this.uuids.get()}`;
|
|
1172
|
+
isRecording = inject(CanvasRecorderService).isRecording;
|
|
1173
|
+
userSettings = this.userSettingsService.settings;
|
|
1174
|
+
constructor() {
|
|
1175
|
+
// we need this component to emit from outputs or call the client when signals change, so an effect
|
|
1176
|
+
// is the recommended solution: https://github.com/angular/angular/issues/57208
|
|
1177
|
+
// when config is provided and autoconnect is on, attempt to automatically connect
|
|
1178
|
+
effect(() => {
|
|
1179
|
+
if (this.autoConnect() && this.config()) {
|
|
1180
|
+
this.connect(this.config());
|
|
1181
|
+
}
|
|
1182
|
+
});
|
|
1183
|
+
// clipboard events
|
|
1184
|
+
effect(() => {
|
|
1185
|
+
if (this.consoleClient()) {
|
|
1186
|
+
this.consoleClipboardUpdated.emit(this.consoleClient().consoleClipboardUpdated());
|
|
1187
|
+
}
|
|
1188
|
+
});
|
|
1189
|
+
effect(() => {
|
|
1190
|
+
const clipboardItem = this.clipboardService.localClipboardContentWritten();
|
|
1191
|
+
if (clipboardItem) {
|
|
1192
|
+
this.localClipboardUpdated.emit(clipboardItem);
|
|
1193
|
+
getTextFromClipboardItem(clipboardItem).then(value => {
|
|
1194
|
+
if (value) {
|
|
1195
|
+
this.browserNotifications.send({ title: "Copied to local clipboard", body: value });
|
|
1196
|
+
}
|
|
1197
|
+
});
|
|
1198
|
+
}
|
|
1199
|
+
});
|
|
1200
|
+
effect(() => {
|
|
1201
|
+
// all supported console clients inject a canvas into the doc. We provide it to the canvas service so it
|
|
1202
|
+
// can be consumed by other components (e.g. the ConsoleToolbarComponent and its implementations)
|
|
1203
|
+
if (this.document && this.consoleClient() && this.consoleClient().connectionStatus() === "connected") {
|
|
1204
|
+
const canvas = this.resolveConsoleCanvas();
|
|
1205
|
+
if (canvas) {
|
|
1206
|
+
this.canvasService.setCanvas(canvas);
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
});
|
|
1210
|
+
// input changes
|
|
1211
|
+
effect(() => {
|
|
1212
|
+
if (this.consoleClient() && this.consoleClient().connectionStatus() === "connected") {
|
|
1213
|
+
this.consoleClient().setIsViewOnly(this.isViewOnly());
|
|
1214
|
+
}
|
|
1215
|
+
});
|
|
1216
|
+
// settings changes
|
|
1217
|
+
effect(() => {
|
|
1218
|
+
const currentSettings = this.userSettingsService.settings();
|
|
1219
|
+
if (this.consoleClient() && this.consoleClient()?.connectionStatus() === "connected") {
|
|
1220
|
+
this.consoleClient().setPreserveAspectRatioOnScale(currentSettings.console.preserveAspectRatioOnScale);
|
|
1221
|
+
}
|
|
1222
|
+
});
|
|
1223
|
+
}
|
|
1224
|
+
async ngOnDestroy() {
|
|
1225
|
+
if (this.consoleClient()) {
|
|
1226
|
+
await this.consoleClient().dispose();
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
handleConsoleRecordingStarted() {
|
|
1230
|
+
return this.browserNotifications.send({ title: "Recording Console", body: "This console is being screen-recorded. Hit \"Record\" again to stop." });
|
|
1231
|
+
}
|
|
1232
|
+
async handleCtrlAltDelSent() {
|
|
1233
|
+
this.ctrlAltDelSent.emit();
|
|
1234
|
+
await this.browserNotifications.send({ title: "Ctrl + Alt + Del sent", body: "Sent a Ctrl + Alt + Del input to the remote machine." });
|
|
1235
|
+
}
|
|
1236
|
+
async handleFullscreen() {
|
|
1237
|
+
if (!this.componentContainer()) {
|
|
1238
|
+
throw new Error("Can't manipulate fullscreen - can't find the host.");
|
|
1239
|
+
}
|
|
1240
|
+
if (!this.fullscreen.isAvailable()) {
|
|
1241
|
+
await this.fullscreen.exitFullscreen();
|
|
1242
|
+
}
|
|
1243
|
+
else {
|
|
1244
|
+
await this.fullscreen.tryFullscreen(this.componentContainer().nativeElement);
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
async handleScreenshotCopied(screenshotData) {
|
|
1248
|
+
this.screenshotCopied.emit(screenshotData);
|
|
1249
|
+
await this.browserNotifications.send({ title: "Screenshot copied", body: "A screenshot of this console has been copied to your clipboard." });
|
|
1250
|
+
return screenshotData;
|
|
1251
|
+
}
|
|
1252
|
+
// automatically invoked if autoConnect is on, but can also be manually invoked outside the component
|
|
1253
|
+
// if retrieved as a ViewChild or whatever
|
|
1254
|
+
async connect(config) {
|
|
1255
|
+
this.logger.log(LogLevel.DEBUG, "Connecting with config", config);
|
|
1256
|
+
// weirdly, even reading this status here causes an infinite loop or something. i think i got too silly with effects.
|
|
1257
|
+
// if (this.consoleClient()?.connectionStatus() !== "disconnected") {
|
|
1258
|
+
// await this.consoleClient()?.disconnect();
|
|
1259
|
+
// }
|
|
1260
|
+
await this.consoleClient()?.disconnect();
|
|
1261
|
+
if (!config.url) {
|
|
1262
|
+
throw new Error("No url provided for console connection.");
|
|
1263
|
+
}
|
|
1264
|
+
if (!this.consoleHostElement().nativeElement) {
|
|
1265
|
+
throw new Error("Couldn't resolve the console host before connection.");
|
|
1266
|
+
}
|
|
1267
|
+
// resolve the console type from component settings + defaults
|
|
1268
|
+
const clientType = this.consoleForgeConfig.defaultConsoleClientType || config.consoleClientType;
|
|
1269
|
+
if (!clientType) {
|
|
1270
|
+
throw new Error("Couldn't resolve the console client type. Did you specify a default using provideConsoleForgeConfig or pass a console type to this component?");
|
|
1271
|
+
}
|
|
1272
|
+
const client = this.consoleClientFactory.get(clientType);
|
|
1273
|
+
// connect
|
|
1274
|
+
await client.connect(config.url, {
|
|
1275
|
+
autoFocusOnConnect: config.autoFocusOnConnect,
|
|
1276
|
+
credentials: config.credentials,
|
|
1277
|
+
hostElement: this.consoleHostElement().nativeElement,
|
|
1278
|
+
});
|
|
1279
|
+
// the order here is important - we only update all the things that care about our console client once we're connected,
|
|
1280
|
+
// otherwise things like trying to set the "view only" property before connection will function strangely.
|
|
1281
|
+
// need to look into ways to validate this via testing
|
|
1282
|
+
this.consoleClient.update(() => client);
|
|
1283
|
+
}
|
|
1284
|
+
async disconnect() {
|
|
1285
|
+
this.logger.log(LogLevel.DEBUG, "Console component disconnect invoked.");
|
|
1286
|
+
await this.consoleClient()?.disconnect();
|
|
1287
|
+
this.consoleClient.update(() => undefined);
|
|
1288
|
+
}
|
|
1289
|
+
resolveConsoleCanvas() {
|
|
1290
|
+
if (!this.document) {
|
|
1291
|
+
return null;
|
|
1292
|
+
}
|
|
1293
|
+
return this.document.querySelector(`#${this.consoleHostElementId} canvas`) || undefined;
|
|
1294
|
+
}
|
|
1295
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConsoleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1296
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "19.2.14", type: ConsoleComponent, isStandalone: true, selector: "cf-console", inputs: { autoConnect: { classPropertyName: "autoConnect", publicName: "autoConnect", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null }, isViewOnly: { classPropertyName: "isViewOnly", publicName: "isViewOnly", isSignal: true, isRequired: false, transformFunction: null }, networkConfig: { classPropertyName: "networkConfig", publicName: "networkConfig", isSignal: true, isRequired: false, transformFunction: null }, toolbarComponent: { classPropertyName: "toolbarComponent", publicName: "toolbarComponent", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { consoleClipboardUpdated: "consoleClipboardUpdated", consoleRecorded: "consoleRecorded", ctrlAltDelSent: "ctrlAltDelSent", localClipboardUpdated: "localClipboardUpdated", networkConnectionRequested: "networkConnectionRequested", networkDisconnectRequested: "networkDisconnectRequested", powerRequestSent: "powerRequestSent", screenshotCopied: "screenshotCopied" }, providers: [
|
|
1297
|
+
// the console component has access to the canvas which is injected by
|
|
1298
|
+
CanvasService
|
|
1299
|
+
], viewQueries: [{ propertyName: "componentContainer", first: true, predicate: ["componentContainer"], descendants: true, isSignal: true }, { propertyName: "consoleHostElement", first: true, predicate: ["consoleHost"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- ===BEGIN LICENSE=== -->\n<!-- Copyright 2025 Carnegie Mellon University. All rights reserved. -->\n<!-- Released under an MIT (SEI)-style license. See the LICENSE.md file for license information. -->\n<!-- ===END LICENSE=== -->\n\n<div #componentContainer class=\"console-component flex\"\n [class.flex-column]=\"userSettings().toolbar.dockTo === 'top' || userSettings().toolbar.dockTo === 'bottom'\">\n\n <cf-console-toolbar\n [class.flex-order-1]=\"userSettings().toolbar.dockTo === 'right' || userSettings().toolbar.dockTo === 'bottom'\"\n [consoleClient]=\"consoleClient()!\" [consoleNetworkConfig]=\"networkConfig()\"\n (canvasRecordingFinished)=\"consoleRecorded.emit($event)\"\n (canvasRecordingStarted)=\"handleConsoleRecordingStarted()\" [customToolbarComponent]=\"toolbarComponent()\"\n (ctrlAltDelSent)=\"handleCtrlAltDelSent()\" (networkConnectionRequested)=\"networkConnectionRequested.emit($event)\"\n (powerRequestSent)=\"powerRequestSent.emit($event)\"\n (networkDisconnectRequested)=\"networkDisconnectRequested.emit()\"\n (screenshotCopied)=\"handleScreenshotCopied($event)\"\n (toggleFullscreen)=\"handleFullscreen()\"></cf-console-toolbar>\n\n <div class=\"console-host-container\"\n [class.flex-order-0]=\"userSettings().toolbar.dockTo === 'right' || userSettings().toolbar.dockTo === 'bottom'\">\n\n <cf-console-status [status]=\"consoleClient()?.connectionStatus()\"></cf-console-status>\n\n <div #consoleHost [id]=\"consoleHostElementId\" class=\"console-host\" [class.recording]=\"isRecording()\"\n [class.view-only]=\"isViewOnly()\">\n </div>\n </div>\n</div>\n", styles: [".console-component{max-width:100%}.console-component:not(:fullscreen) ::ng-deep canvas{aspect-ratio:16/9!important;max-height:100%!important;max-width:100%!important;position:unset!important}cf-console-toolbar{display:block;z-index:5}.console-host-container{flex-grow:1;max-width:100%}.console-host{width:100%;height:100%;margin:0 auto}.console-host.recording{outline:4px solid #ee402e}.console-host.wmks{display:flex;justify-content:center;aspect-ratio:16/9}.flex{display:flex;flex-direction:row}.flex.flex-column{flex-direction:column}.flex-order-0{order:0}.flex-order-1{order:1}::ng-deep .view-only canvas{pointer-events:none!important}\n"], dependencies: [{ kind: "component", type: ConsoleStatusComponent, selector: "cf-console-status", inputs: ["status"] }, { kind: "component", type: ConsoleToolbarComponent, selector: "cf-console-toolbar", inputs: ["consoleClient", "consoleNetworkConfig", "customToolbarComponent"], outputs: ["canvasRecordingStarted", "canvasRecordingFinished", "ctrlAltDelSent", "networkConnectionRequested", "networkDisconnectRequested", "powerRequestSent", "screenshotCopied", "toggleFullscreen"] }] });
|
|
1300
|
+
}
|
|
1301
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ConsoleComponent, decorators: [{
|
|
1302
|
+
type: Component,
|
|
1303
|
+
args: [{ selector: 'cf-console', standalone: true, imports: [
|
|
1304
|
+
ConsoleStatusComponent,
|
|
1305
|
+
ConsoleToolbarComponent
|
|
1306
|
+
], providers: [
|
|
1307
|
+
// the console component has access to the canvas which is injected by
|
|
1308
|
+
CanvasService
|
|
1309
|
+
], template: "<!-- ===BEGIN LICENSE=== -->\n<!-- Copyright 2025 Carnegie Mellon University. All rights reserved. -->\n<!-- Released under an MIT (SEI)-style license. See the LICENSE.md file for license information. -->\n<!-- ===END LICENSE=== -->\n\n<div #componentContainer class=\"console-component flex\"\n [class.flex-column]=\"userSettings().toolbar.dockTo === 'top' || userSettings().toolbar.dockTo === 'bottom'\">\n\n <cf-console-toolbar\n [class.flex-order-1]=\"userSettings().toolbar.dockTo === 'right' || userSettings().toolbar.dockTo === 'bottom'\"\n [consoleClient]=\"consoleClient()!\" [consoleNetworkConfig]=\"networkConfig()\"\n (canvasRecordingFinished)=\"consoleRecorded.emit($event)\"\n (canvasRecordingStarted)=\"handleConsoleRecordingStarted()\" [customToolbarComponent]=\"toolbarComponent()\"\n (ctrlAltDelSent)=\"handleCtrlAltDelSent()\" (networkConnectionRequested)=\"networkConnectionRequested.emit($event)\"\n (powerRequestSent)=\"powerRequestSent.emit($event)\"\n (networkDisconnectRequested)=\"networkDisconnectRequested.emit()\"\n (screenshotCopied)=\"handleScreenshotCopied($event)\"\n (toggleFullscreen)=\"handleFullscreen()\"></cf-console-toolbar>\n\n <div class=\"console-host-container\"\n [class.flex-order-0]=\"userSettings().toolbar.dockTo === 'right' || userSettings().toolbar.dockTo === 'bottom'\">\n\n <cf-console-status [status]=\"consoleClient()?.connectionStatus()\"></cf-console-status>\n\n <div #consoleHost [id]=\"consoleHostElementId\" class=\"console-host\" [class.recording]=\"isRecording()\"\n [class.view-only]=\"isViewOnly()\">\n </div>\n </div>\n</div>\n", styles: [".console-component{max-width:100%}.console-component:not(:fullscreen) ::ng-deep canvas{aspect-ratio:16/9!important;max-height:100%!important;max-width:100%!important;position:unset!important}cf-console-toolbar{display:block;z-index:5}.console-host-container{flex-grow:1;max-width:100%}.console-host{width:100%;height:100%;margin:0 auto}.console-host.recording{outline:4px solid #ee402e}.console-host.wmks{display:flex;justify-content:center;aspect-ratio:16/9}.flex{display:flex;flex-direction:row}.flex.flex-column{flex-direction:column}.flex-order-0{order:0}.flex-order-1{order:1}::ng-deep .view-only canvas{pointer-events:none!important}\n"] }]
|
|
1310
|
+
}], ctorParameters: () => [] });
|
|
1311
|
+
|
|
1312
|
+
// ===BEGIN LICENSE===
|
|
1313
|
+
// Copyright 2025 Carnegie Mellon University. All rights reserved.
|
|
1314
|
+
// Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
|
|
1315
|
+
// ===END LICENSE===
|
|
1316
|
+
|
|
1317
|
+
// ===BEGIN LICENSE===
|
|
1318
|
+
// Copyright 2025 Carnegie Mellon University. All rights reserved.
|
|
1319
|
+
// Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
|
|
1320
|
+
// ===END LICENSE===
|
|
1321
|
+
function provideConsoleForge(config) {
|
|
1322
|
+
// merge provided with defaults
|
|
1323
|
+
const finalConfig = config ? deepMerge(defaultCfConfig, config) : defaultCfConfig;
|
|
1324
|
+
// provide to the env
|
|
1325
|
+
return makeEnvironmentProviders([
|
|
1326
|
+
{ provide: ClipboardService },
|
|
1327
|
+
{ provide: ConsoleClientFactoryService },
|
|
1328
|
+
{ provide: FullScreenService },
|
|
1329
|
+
{ provide: LoggerService },
|
|
1330
|
+
{ provide: UserSettingsService },
|
|
1331
|
+
{ provide: UuidService },
|
|
1332
|
+
{
|
|
1333
|
+
provide: ConsoleForgeConfig,
|
|
1334
|
+
useValue: finalConfig
|
|
1335
|
+
},
|
|
1336
|
+
]);
|
|
1337
|
+
}
|
|
1338
|
+
|
|
1339
|
+
// ===BEGIN LICENSE===
|
|
1340
|
+
// Copyright 2025 Carnegie Mellon University. All rights reserved.
|
|
1341
|
+
// Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
|
|
1342
|
+
// ===END LICENSE===
|
|
1343
|
+
|
|
1344
|
+
// ===BEGIN LICENSE===
|
|
1345
|
+
// Copyright 2025 Carnegie Mellon University. All rights reserved.
|
|
1346
|
+
// Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
|
|
1347
|
+
// ===END LICENSE===
|
|
1348
|
+
|
|
1349
|
+
// ===BEGIN LICENSE===
|
|
1350
|
+
// Copyright 2025 Carnegie Mellon University. All rights reserved.
|
|
1351
|
+
// Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
|
|
1352
|
+
// ===END LICENSE===
|
|
1353
|
+
|
|
1354
|
+
// ===BEGIN LICENSE===
|
|
1355
|
+
// Copyright 2025 Carnegie Mellon University. All rights reserved.
|
|
1356
|
+
// Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
|
|
1357
|
+
// ===END LICENSE===
|
|
1358
|
+
|
|
1359
|
+
// ===BEGIN LICENSE===
|
|
1360
|
+
// Copyright 2025 Carnegie Mellon University. All rights reserved.
|
|
1361
|
+
// Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
|
|
1362
|
+
// ===END LICENSE===
|
|
1363
|
+
|
|
1364
|
+
// ===BEGIN LICENSE===
|
|
1365
|
+
// Copyright 2025 Carnegie Mellon University. All rights reserved.
|
|
1366
|
+
// Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
|
|
1367
|
+
// ===END LICENSE===
|
|
1368
|
+
|
|
1369
|
+
// ===BEGIN LICENSE===
|
|
1370
|
+
// Copyright 2025 Carnegie Mellon University. All rights reserved.
|
|
1371
|
+
// Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
|
|
1372
|
+
// ===END LICENSE===
|
|
1373
|
+
|
|
1374
|
+
// ===BEGIN LICENSE===
|
|
1375
|
+
// Copyright 2025 Carnegie Mellon University. All rights reserved.
|
|
1376
|
+
// Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
|
|
1377
|
+
// ===END LICENSE===
|
|
1378
|
+
|
|
1379
|
+
// ===BEGIN LICENSE===
|
|
1380
|
+
// Copyright 2025 Carnegie Mellon University. All rights reserved.
|
|
1381
|
+
// Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
|
|
1382
|
+
// ===END LICENSE===
|
|
1383
|
+
|
|
1384
|
+
// ===BEGIN LICENSE===
|
|
1385
|
+
// Copyright 2025 Carnegie Mellon University. All rights reserved.
|
|
1386
|
+
// Released under an MIT (SEI)-style license. See the LICENSE.md file for license information.
|
|
1387
|
+
// ===END LICENSE===
|
|
1388
|
+
/*
|
|
1389
|
+
* Public API Surface of console-forge
|
|
1390
|
+
*/
|
|
1391
|
+
|
|
1392
|
+
/**
|
|
1393
|
+
* Generated bundle index. Do not edit.
|
|
1394
|
+
*/
|
|
1395
|
+
|
|
1396
|
+
export { ClassOnHoverDirective, ConsoleComponent, LogLevel, UserSettingsService, getClipboardItemFromText, getTextFromClipboardItem, provideConsoleForge };
|
|
1397
|
+
//# sourceMappingURL=cmusei-console-forge.mjs.map
|