max-agent-ui 0.0.25 → 0.0.27
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/fesm2022/max-agent-ui.mjs +299 -40
- package/fesm2022/max-agent-ui.mjs.map +1 -1
- package/index.d.ts +56 -18
- package/package.json +1 -1
|
@@ -19,7 +19,7 @@ import * as i10 from 'primeng/textarea';
|
|
|
19
19
|
import { TextareaModule } from 'primeng/textarea';
|
|
20
20
|
import * as i11 from 'primeng/tooltip';
|
|
21
21
|
import { TooltipModule } from 'primeng/tooltip';
|
|
22
|
-
import { throwError, Observable, of, delay, switchMap } from 'rxjs';
|
|
22
|
+
import { throwError, Observable, of, delay, map, switchMap } from 'rxjs';
|
|
23
23
|
import { marked } from 'marked';
|
|
24
24
|
|
|
25
25
|
const INITIAL_MESSAGE = 'Hi! 👋';
|
|
@@ -257,6 +257,21 @@ class MaxAssistantService {
|
|
|
257
257
|
};
|
|
258
258
|
return this.postMessage(request, assistantConfig);
|
|
259
259
|
}
|
|
260
|
+
retrieveAnalyticsPage(message, analyticsPage, conversationId, config = {}, history = []) {
|
|
261
|
+
const assistantConfig = this.mergeConfig(config);
|
|
262
|
+
const context = this.getContext(assistantConfig);
|
|
263
|
+
const user = this.getRequestUser(assistantConfig);
|
|
264
|
+
const request = {
|
|
265
|
+
message,
|
|
266
|
+
conversationId,
|
|
267
|
+
history,
|
|
268
|
+
app: this.getApp(assistantConfig),
|
|
269
|
+
...(user ? { user } : {}),
|
|
270
|
+
...(context ? { context } : {}),
|
|
271
|
+
analyticsPage
|
|
272
|
+
};
|
|
273
|
+
return this.postMessage(request, assistantConfig);
|
|
274
|
+
}
|
|
260
275
|
postMessage(request, config, onProgress) {
|
|
261
276
|
if (!this.http) {
|
|
262
277
|
return throwError(() => new Error('HttpClient is not available. Add provideHttpClient() to the host app.'));
|
|
@@ -590,43 +605,105 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImpo
|
|
|
590
605
|
args: [{ providedIn: 'root' }]
|
|
591
606
|
}] });
|
|
592
607
|
|
|
593
|
-
const MOCK_SUPPORT_TAGS = [
|
|
594
|
-
{ value: 'scheduling', label: 'Scheduling & Rotas', icon: 'pi pi-calendar', severity: 'info' },
|
|
595
|
-
{ value: 'timesheets', label: 'Timesheets', icon: 'pi pi-clock', severity: 'secondary' },
|
|
596
|
-
{ value: 'clocking', label: 'Clocking & Attendance', icon: 'pi pi-stopwatch', severity: 'warn' },
|
|
597
|
-
{ value: 'people', label: 'People', icon: 'pi pi-user', severity: 'info' },
|
|
598
|
-
{ value: 'teams-locations', label: 'Teams & Locations', icon: 'pi pi-building', severity: 'secondary' },
|
|
599
|
-
{ value: 'holiday', label: 'Holiday & Time Off', icon: 'pi pi-sun', severity: 'success' },
|
|
600
|
-
{ value: 'payroll', label: 'Payroll & Pay', icon: 'pi pi-wallet', severity: 'success' },
|
|
601
|
-
{ value: 'reporting', label: 'Reporting & Insights', icon: 'pi pi-chart-bar', severity: 'info' },
|
|
602
|
-
{ value: 'configuration', label: 'Configuration', icon: 'pi pi-cog', severity: 'secondary' },
|
|
603
|
-
{ value: 'permissions', label: 'Permissions & Access', icon: 'pi pi-shield', severity: 'warn' },
|
|
604
|
-
{ value: 'performance', label: 'Performance', icon: 'pi pi-chart-line', severity: 'success' },
|
|
605
|
-
{ value: 'technical', label: 'Technical Issue', icon: 'pi pi-wrench', severity: 'danger' }
|
|
606
|
-
];
|
|
607
|
-
let mockTicketSequence = 1000;
|
|
608
608
|
class MaxAssistantSupportService {
|
|
609
|
-
|
|
610
|
-
|
|
609
|
+
config;
|
|
610
|
+
http;
|
|
611
|
+
ticketsEndpoint = '/ticket';
|
|
612
|
+
tagsEndpoint = '/selection/lookup/supportticket/tag';
|
|
613
|
+
severitiesEndpoint = '/selection/lookup/supportticket/severity';
|
|
614
|
+
constructor(config, http) {
|
|
615
|
+
this.config = config;
|
|
616
|
+
this.http = http;
|
|
617
|
+
}
|
|
611
618
|
getSupportTags() {
|
|
612
|
-
|
|
619
|
+
if (!this.http) {
|
|
620
|
+
return throwError(() => new Error('HttpClient is not available. Add provideHttpClient() to the host app.'));
|
|
621
|
+
}
|
|
622
|
+
return this.http.get(this.tagsEndpoint, { headers: this.getHeaders(this.mergeConfig({})) }).pipe(map(tags => tags.map(tag => ({
|
|
623
|
+
...tag,
|
|
624
|
+
icon: 'pi pi-tag',
|
|
625
|
+
severity: 'info'
|
|
626
|
+
}))));
|
|
613
627
|
}
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
628
|
+
getSupportSeverities() {
|
|
629
|
+
if (!this.http) {
|
|
630
|
+
return throwError(() => new Error('HttpClient is not available. Add provideHttpClient() to the host app.'));
|
|
631
|
+
}
|
|
632
|
+
return this.http.get(this.severitiesEndpoint, { headers: this.getHeaders(this.mergeConfig({})) });
|
|
633
|
+
}
|
|
634
|
+
submitTicket(ticket, config = {}) {
|
|
635
|
+
if (!this.http) {
|
|
636
|
+
return throwError(() => new Error('HttpClient is not available. Add provideHttpClient() to the host app.'));
|
|
637
|
+
}
|
|
638
|
+
const mergedConfig = this.mergeConfig(config);
|
|
639
|
+
const response$ = this.http.post(this.ticketsEndpoint, {
|
|
640
|
+
subject: ticket.subject,
|
|
641
|
+
body: ticket.query,
|
|
642
|
+
severity: ticket.severity,
|
|
643
|
+
tags: ticket.tags.map(({ id, label }) => ({ id, label }))
|
|
644
|
+
}, {
|
|
645
|
+
headers: this.getHeaders(mergedConfig),
|
|
646
|
+
responseType: 'text'
|
|
647
|
+
});
|
|
648
|
+
return response$.pipe(map(response => this.toTicketResponse(response)));
|
|
649
|
+
}
|
|
650
|
+
toTicketResponse(_response) {
|
|
651
|
+
return {
|
|
617
652
|
success: true,
|
|
618
|
-
|
|
619
|
-
message: 'Your support ticket has been raised successfully.',
|
|
653
|
+
message: 'Your support ticket has been created. You will receive an email with your reference number shortly.',
|
|
620
654
|
submittedAt: new Date().toISOString()
|
|
621
|
-
}
|
|
655
|
+
};
|
|
656
|
+
}
|
|
657
|
+
getHeaders(config) {
|
|
658
|
+
const user = this.getUser(config);
|
|
659
|
+
const configuredHeaders = typeof config.requestHeaders === 'function'
|
|
660
|
+
? config.requestHeaders()
|
|
661
|
+
: config.requestHeaders ?? {};
|
|
662
|
+
let headers = new HttpHeaders({ 'Content-Type': 'application/json' });
|
|
663
|
+
for (const [name, value] of Object.entries(configuredHeaders)) {
|
|
664
|
+
if (name.trim() && value.trim()) {
|
|
665
|
+
headers = headers.set(name.trim(), value.trim());
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
if (user.token) {
|
|
669
|
+
headers = headers.set('x-auth-token', String(user.token));
|
|
670
|
+
}
|
|
671
|
+
if (user.version) {
|
|
672
|
+
headers = headers.set('x-version', String(user.version));
|
|
673
|
+
}
|
|
674
|
+
return headers;
|
|
675
|
+
}
|
|
676
|
+
getUser(config) {
|
|
677
|
+
return typeof config.user === 'function' ? config.user() : config.user ?? {};
|
|
622
678
|
}
|
|
623
|
-
|
|
679
|
+
mergeConfig(config) {
|
|
680
|
+
const merged = {
|
|
681
|
+
...this.config,
|
|
682
|
+
...Object.fromEntries(Object.entries(config).filter(([, value]) => value !== undefined))
|
|
683
|
+
};
|
|
684
|
+
if (config.user === undefined) {
|
|
685
|
+
return merged;
|
|
686
|
+
}
|
|
687
|
+
return {
|
|
688
|
+
...merged,
|
|
689
|
+
user: {
|
|
690
|
+
...this.getUser(this.config),
|
|
691
|
+
...this.getUser(config)
|
|
692
|
+
}
|
|
693
|
+
};
|
|
694
|
+
}
|
|
695
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: MaxAssistantSupportService, deps: [{ token: MAX_ASSISTANT_CONFIG }, { token: i1.HttpClient, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
624
696
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: MaxAssistantSupportService, providedIn: 'root' });
|
|
625
697
|
}
|
|
626
698
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: MaxAssistantSupportService, decorators: [{
|
|
627
699
|
type: Injectable,
|
|
628
700
|
args: [{ providedIn: 'root' }]
|
|
629
|
-
}]
|
|
701
|
+
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
702
|
+
type: Inject,
|
|
703
|
+
args: [MAX_ASSISTANT_CONFIG]
|
|
704
|
+
}] }, { type: i1.HttpClient, decorators: [{
|
|
705
|
+
type: Optional
|
|
706
|
+
}] }] });
|
|
630
707
|
|
|
631
708
|
const ASSISTANT_UI_COPY = {
|
|
632
709
|
title: 'Max',
|
|
@@ -678,6 +755,8 @@ class MaxAssistantComponent {
|
|
|
678
755
|
messages = signal([], ...(ngDevMode ? [{ debugName: "messages" }] : []));
|
|
679
756
|
expandedDetailMessageIds = signal(new Set(), ...(ngDevMode ? [{ debugName: "expandedDetailMessageIds" }] : []));
|
|
680
757
|
expandedTraceStepKeys = signal(new Set(), ...(ngDevMode ? [{ debugName: "expandedTraceStepKeys" }] : []));
|
|
758
|
+
loadingTablePage = signal(undefined, ...(ngDevMode ? [{ debugName: "loadingTablePage" }] : []));
|
|
759
|
+
tablePageErrors = signal({}, ...(ngDevMode ? [{ debugName: "tablePageErrors" }] : []));
|
|
681
760
|
feedbackVisible = signal(false, ...(ngDevMode ? [{ debugName: "feedbackVisible" }] : []));
|
|
682
761
|
feedbackSubmitting = signal(false, ...(ngDevMode ? [{ debugName: "feedbackSubmitting" }] : []));
|
|
683
762
|
feedbackResult = signal(undefined, ...(ngDevMode ? [{ debugName: "feedbackResult" }] : []));
|
|
@@ -695,14 +774,10 @@ class MaxAssistantComponent {
|
|
|
695
774
|
supportTicketSubmitting = signal(false, ...(ngDevMode ? [{ debugName: "supportTicketSubmitting" }] : []));
|
|
696
775
|
supportTagsLoading = signal(false, ...(ngDevMode ? [{ debugName: "supportTagsLoading" }] : []));
|
|
697
776
|
supportTags = signal([], ...(ngDevMode ? [{ debugName: "supportTags" }] : []));
|
|
777
|
+
supportSeverities = signal([], ...(ngDevMode ? [{ debugName: "supportSeverities" }] : []));
|
|
698
778
|
supportTicketResult = signal(undefined, ...(ngDevMode ? [{ debugName: "supportTicketResult" }] : []));
|
|
699
779
|
supportTicketError = signal(undefined, ...(ngDevMode ? [{ debugName: "supportTicketError" }] : []));
|
|
700
|
-
|
|
701
|
-
{ label: 'Low', value: 'low', severity: 'success' },
|
|
702
|
-
{ label: 'Medium', value: 'medium', severity: 'info' },
|
|
703
|
-
{ label: 'High', value: 'high', severity: 'warn' },
|
|
704
|
-
{ label: 'Critical', value: 'critical', severity: 'danger' }
|
|
705
|
-
];
|
|
780
|
+
supportTicketSubmissionFailed = signal(false, ...(ngDevMode ? [{ debugName: "supportTicketSubmissionFailed" }] : []));
|
|
706
781
|
supportTicketForm = this.createSupportTicketForm();
|
|
707
782
|
constructor(assistantService, exportService, feedbackService, supportService, destroyRef, defaultConfig) {
|
|
708
783
|
this.assistantService = assistantService;
|
|
@@ -755,6 +830,8 @@ class MaxAssistantComponent {
|
|
|
755
830
|
this.conversationId.set(undefined);
|
|
756
831
|
this.expandedDetailMessageIds.set(new Set());
|
|
757
832
|
this.expandedTraceStepKeys.set(new Set());
|
|
833
|
+
this.loadingTablePage.set(undefined);
|
|
834
|
+
this.tablePageErrors.set({});
|
|
758
835
|
this.messages.set(this.createDefaultMessages());
|
|
759
836
|
this.scrollToLatest();
|
|
760
837
|
}
|
|
@@ -898,7 +975,9 @@ class MaxAssistantComponent {
|
|
|
898
975
|
this.supportTicketForm = this.createSupportTicketForm(user);
|
|
899
976
|
this.supportTicketResult.set(undefined);
|
|
900
977
|
this.supportTicketError.set(undefined);
|
|
978
|
+
this.supportTicketSubmissionFailed.set(false);
|
|
901
979
|
this.supportTags.set([]);
|
|
980
|
+
this.supportSeverities.set([]);
|
|
902
981
|
this.supportTagsLoading.set(true);
|
|
903
982
|
this.supportTicketVisible.set(true);
|
|
904
983
|
this.supportService
|
|
@@ -914,6 +993,13 @@ class MaxAssistantComponent {
|
|
|
914
993
|
this.supportTicketError.set('Support tags could not be loaded. You can still submit the ticket.');
|
|
915
994
|
}
|
|
916
995
|
});
|
|
996
|
+
this.supportService
|
|
997
|
+
.getSupportSeverities()
|
|
998
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
999
|
+
.subscribe({
|
|
1000
|
+
next: severities => this.supportSeverities.set(severities),
|
|
1001
|
+
error: () => this.supportTicketError.set('Severity options could not be loaded. Please try again.')
|
|
1002
|
+
});
|
|
917
1003
|
setTimeout(() => this.supportQueryInput?.nativeElement.focus());
|
|
918
1004
|
}
|
|
919
1005
|
closeSupportTicket(restoreComposerFocus = true) {
|
|
@@ -921,6 +1007,7 @@ class MaxAssistantComponent {
|
|
|
921
1007
|
this.supportTicketSubmitting.set(false);
|
|
922
1008
|
this.supportTicketResult.set(undefined);
|
|
923
1009
|
this.supportTicketError.set(undefined);
|
|
1010
|
+
this.supportTicketSubmissionFailed.set(false);
|
|
924
1011
|
if (restoreComposerFocus) {
|
|
925
1012
|
setTimeout(() => this.focusComposer());
|
|
926
1013
|
}
|
|
@@ -933,12 +1020,21 @@ class MaxAssistantComponent {
|
|
|
933
1020
|
this.supportTicketForm.severity &&
|
|
934
1021
|
!this.supportTicketSubmitting());
|
|
935
1022
|
}
|
|
1023
|
+
supportSeverityColor(color) {
|
|
1024
|
+
const value = color?.trim() ?? '';
|
|
1025
|
+
return value ? (value.startsWith('#') ? value : `#${value}`) : 'var(--max-accent)';
|
|
1026
|
+
}
|
|
936
1027
|
submitSupportTicket() {
|
|
937
1028
|
if (!this.canSubmitSupportTicket()) {
|
|
938
1029
|
return;
|
|
939
1030
|
}
|
|
1031
|
+
const severity = this.supportTicketForm.severity;
|
|
1032
|
+
if (!severity) {
|
|
1033
|
+
return;
|
|
1034
|
+
}
|
|
940
1035
|
this.supportTicketSubmitting.set(true);
|
|
941
1036
|
this.supportTicketError.set(undefined);
|
|
1037
|
+
this.supportTicketSubmissionFailed.set(false);
|
|
942
1038
|
this.supportService
|
|
943
1039
|
.submitTicket({
|
|
944
1040
|
name: this.supportTicketForm.name.trim(),
|
|
@@ -948,10 +1044,10 @@ class MaxAssistantComponent {
|
|
|
948
1044
|
: {}),
|
|
949
1045
|
subject: this.supportTicketForm.subject.trim(),
|
|
950
1046
|
query: this.supportTicketForm.query.trim(),
|
|
951
|
-
severity
|
|
952
|
-
tags:
|
|
1047
|
+
severity,
|
|
1048
|
+
tags: this.supportTicketForm.tags.map(({ id, label }) => ({ id, label })),
|
|
953
1049
|
app: this.app ?? this.defaultConfig.app ?? 'nemesys'
|
|
954
|
-
})
|
|
1050
|
+
}, this.getAssistantConfig())
|
|
955
1051
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
956
1052
|
.subscribe({
|
|
957
1053
|
next: result => {
|
|
@@ -960,7 +1056,8 @@ class MaxAssistantComponent {
|
|
|
960
1056
|
},
|
|
961
1057
|
error: () => {
|
|
962
1058
|
this.supportTicketSubmitting.set(false);
|
|
963
|
-
this.
|
|
1059
|
+
this.supportTicketSubmissionFailed.set(true);
|
|
1060
|
+
this.supportTicketError.set('Your ticket could not be created. Please try again shortly.');
|
|
964
1061
|
}
|
|
965
1062
|
});
|
|
966
1063
|
}
|
|
@@ -1146,6 +1243,66 @@ class MaxAssistantComponent {
|
|
|
1146
1243
|
getResponseGrid(responseDetails) {
|
|
1147
1244
|
return responseDetails.grid?.length ? responseDetails.grid : responseDetails.tables ?? [];
|
|
1148
1245
|
}
|
|
1246
|
+
retrieveNextTablePage(message, table, tableIndex) {
|
|
1247
|
+
const pagination = table.pagination;
|
|
1248
|
+
if (!pagination || !this.hasNextTablePage(table) || this.isSending()) {
|
|
1249
|
+
return;
|
|
1250
|
+
}
|
|
1251
|
+
const nextOffset = table.rows.length;
|
|
1252
|
+
if (nextOffset % pagination.pageSize !== 0) {
|
|
1253
|
+
return;
|
|
1254
|
+
}
|
|
1255
|
+
const tableKey = this.tablePageKey(message.id, tableIndex);
|
|
1256
|
+
const history = this.getConversationHistory();
|
|
1257
|
+
this.tablePageErrors.update(errors => {
|
|
1258
|
+
const next = { ...errors };
|
|
1259
|
+
delete next[tableKey];
|
|
1260
|
+
return next;
|
|
1261
|
+
});
|
|
1262
|
+
this.loadingTablePage.set(tableKey);
|
|
1263
|
+
this.isSending.set(true);
|
|
1264
|
+
this.assistantService
|
|
1265
|
+
.retrieveAnalyticsPage(pagination.query, { offset: nextOffset, pageSize: 250 }, this.conversationId(), this.getAssistantConfig(), history)
|
|
1266
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
1267
|
+
.subscribe({
|
|
1268
|
+
next: response => {
|
|
1269
|
+
this.conversationId.set(response.conversationId);
|
|
1270
|
+
this.mergeTablePage(message.id, tableIndex, response, pagination.query);
|
|
1271
|
+
this.loadingTablePage.set(undefined);
|
|
1272
|
+
this.isSending.set(false);
|
|
1273
|
+
},
|
|
1274
|
+
error: error => {
|
|
1275
|
+
this.tablePageErrors.update(errors => ({
|
|
1276
|
+
...errors,
|
|
1277
|
+
[tableKey]: this.resolveErrorMessage(error)
|
|
1278
|
+
}));
|
|
1279
|
+
this.loadingTablePage.set(undefined);
|
|
1280
|
+
this.isSending.set(false);
|
|
1281
|
+
}
|
|
1282
|
+
});
|
|
1283
|
+
}
|
|
1284
|
+
tablePageStatus(table) {
|
|
1285
|
+
const pagination = table.pagination;
|
|
1286
|
+
return pagination
|
|
1287
|
+
? `${Math.min(table.rows.length, pagination.totalRecords).toLocaleString()} of ${pagination.totalRecords.toLocaleString()} records retrieved`
|
|
1288
|
+
: '';
|
|
1289
|
+
}
|
|
1290
|
+
hasNextTablePage(table) {
|
|
1291
|
+
const pagination = table.pagination;
|
|
1292
|
+
return Boolean(pagination &&
|
|
1293
|
+
pagination.remainingRecords > 0 &&
|
|
1294
|
+
pagination.nextOffset !== undefined &&
|
|
1295
|
+
table.rows.length < pagination.totalRecords);
|
|
1296
|
+
}
|
|
1297
|
+
nextTablePageLabel(pagination) {
|
|
1298
|
+
return `Retrieve next ${Math.min(pagination.pageSize, pagination.remainingRecords).toLocaleString()} records`;
|
|
1299
|
+
}
|
|
1300
|
+
isTablePageLoading(messageId, tableIndex) {
|
|
1301
|
+
return this.loadingTablePage() === this.tablePageKey(messageId, tableIndex);
|
|
1302
|
+
}
|
|
1303
|
+
tablePageError(messageId, tableIndex) {
|
|
1304
|
+
return this.tablePageErrors()[this.tablePageKey(messageId, tableIndex)];
|
|
1305
|
+
}
|
|
1149
1306
|
exportTable(table) {
|
|
1150
1307
|
void this.exportService.exportTableToExcel(table);
|
|
1151
1308
|
}
|
|
@@ -1324,6 +1481,108 @@ class MaxAssistantComponent {
|
|
|
1324
1481
|
: message));
|
|
1325
1482
|
this.scrollToLatest();
|
|
1326
1483
|
}
|
|
1484
|
+
mergeTablePage(messageId, tableIndex, response, userQuery) {
|
|
1485
|
+
const nextDisplay = this.createDisplayResponse(response, userQuery);
|
|
1486
|
+
const nextTable = this.getResponseGrid(nextDisplay)[0];
|
|
1487
|
+
const tableKey = this.tablePageKey(messageId, tableIndex);
|
|
1488
|
+
this.messages.update(messages => messages.map(message => {
|
|
1489
|
+
if (message.id !== messageId) {
|
|
1490
|
+
return message;
|
|
1491
|
+
}
|
|
1492
|
+
const developerTrace = this.mergeDeveloperTraces(message.developerTrace, response.developerTrace);
|
|
1493
|
+
if (!nextTable || !message.displayResponse) {
|
|
1494
|
+
this.tablePageErrors.update(errors => ({
|
|
1495
|
+
...errors,
|
|
1496
|
+
[tableKey]: response.answer
|
|
1497
|
+
}));
|
|
1498
|
+
return { ...message, developerTrace };
|
|
1499
|
+
}
|
|
1500
|
+
const tables = [...this.getResponseGrid(message.displayResponse)];
|
|
1501
|
+
const currentTable = tables[tableIndex];
|
|
1502
|
+
if (!currentTable) {
|
|
1503
|
+
return { ...message, developerTrace };
|
|
1504
|
+
}
|
|
1505
|
+
const rowOffset = currentTable.rows.length;
|
|
1506
|
+
if (nextTable.pagination &&
|
|
1507
|
+
nextTable.pagination.offset !== rowOffset) {
|
|
1508
|
+
this.tablePageErrors.update(errors => ({
|
|
1509
|
+
...errors,
|
|
1510
|
+
[tableKey]: 'The next records could not be retrieved in sequence. Please try the query again.'
|
|
1511
|
+
}));
|
|
1512
|
+
return { ...message, developerTrace };
|
|
1513
|
+
}
|
|
1514
|
+
const totalRecords = nextTable.pagination?.totalRecords ?? rowOffset + nextTable.rows.length;
|
|
1515
|
+
const rows = [...currentTable.rows, ...nextTable.rows].slice(0, totalRecords);
|
|
1516
|
+
const remainingRecords = Math.max(totalRecords - rows.length, 0);
|
|
1517
|
+
const pagination = nextTable.pagination
|
|
1518
|
+
? {
|
|
1519
|
+
query: nextTable.pagination.query,
|
|
1520
|
+
offset: 0,
|
|
1521
|
+
pageSize: nextTable.pagination.pageSize,
|
|
1522
|
+
totalRecords,
|
|
1523
|
+
returnedRecords: rows.length,
|
|
1524
|
+
remainingRecords,
|
|
1525
|
+
...(remainingRecords > 0 ? { nextOffset: rows.length } : {})
|
|
1526
|
+
}
|
|
1527
|
+
: currentTable.pagination;
|
|
1528
|
+
tables[tableIndex] = {
|
|
1529
|
+
...currentTable,
|
|
1530
|
+
rows,
|
|
1531
|
+
...(nextTable.actions?.length
|
|
1532
|
+
? {
|
|
1533
|
+
actions: [
|
|
1534
|
+
...(currentTable.actions ?? []),
|
|
1535
|
+
...nextTable.actions.map(action => ({
|
|
1536
|
+
...action,
|
|
1537
|
+
rowIndex: action.rowIndex + rowOffset
|
|
1538
|
+
}))
|
|
1539
|
+
]
|
|
1540
|
+
}
|
|
1541
|
+
: {}),
|
|
1542
|
+
...(pagination ? { pagination } : {})
|
|
1543
|
+
};
|
|
1544
|
+
return {
|
|
1545
|
+
...message,
|
|
1546
|
+
displayResponse: {
|
|
1547
|
+
...message.displayResponse,
|
|
1548
|
+
grid: tables,
|
|
1549
|
+
tables
|
|
1550
|
+
},
|
|
1551
|
+
developerTrace
|
|
1552
|
+
};
|
|
1553
|
+
}));
|
|
1554
|
+
this.scrollToLatest();
|
|
1555
|
+
}
|
|
1556
|
+
mergeDeveloperTraces(current, next) {
|
|
1557
|
+
if (!current) {
|
|
1558
|
+
return next;
|
|
1559
|
+
}
|
|
1560
|
+
if (!next) {
|
|
1561
|
+
return current;
|
|
1562
|
+
}
|
|
1563
|
+
const lastId = Math.max(0, ...current.steps.map(step => step.id));
|
|
1564
|
+
const steps = [
|
|
1565
|
+
...current.steps,
|
|
1566
|
+
...next.steps.map((step, index) => ({ ...step, id: lastId + index + 1 }))
|
|
1567
|
+
];
|
|
1568
|
+
if (!current.run || !next.run) {
|
|
1569
|
+
return { ...(next.run ?? current.run ? { run: next.run ?? current.run } : {}), steps };
|
|
1570
|
+
}
|
|
1571
|
+
return {
|
|
1572
|
+
run: {
|
|
1573
|
+
...current.run,
|
|
1574
|
+
completedAt: next.run.completedAt,
|
|
1575
|
+
durationMs: current.run.durationMs + next.run.durationMs,
|
|
1576
|
+
llmCalls: current.run.llmCalls + next.run.llmCalls,
|
|
1577
|
+
embeddingCalls: current.run.embeddingCalls + next.run.embeddingCalls,
|
|
1578
|
+
apiCalls: current.run.apiCalls + next.run.apiCalls
|
|
1579
|
+
},
|
|
1580
|
+
steps
|
|
1581
|
+
};
|
|
1582
|
+
}
|
|
1583
|
+
tablePageKey(messageId, tableIndex) {
|
|
1584
|
+
return `${messageId}:${tableIndex}`;
|
|
1585
|
+
}
|
|
1327
1586
|
createDefaultMessages() {
|
|
1328
1587
|
if (!this.bootstrapConfig.initialMessage) {
|
|
1329
1588
|
return [];
|
|
@@ -1374,7 +1633,7 @@ class MaxAssistantComponent {
|
|
|
1374
1633
|
phone: this.getUserText(user, ['phone', 'phoneNumber', 'mobile']),
|
|
1375
1634
|
subject: '',
|
|
1376
1635
|
query: '',
|
|
1377
|
-
severity:
|
|
1636
|
+
severity: null,
|
|
1378
1637
|
tags: []
|
|
1379
1638
|
};
|
|
1380
1639
|
}
|
|
@@ -1617,7 +1876,7 @@ class MaxAssistantComponent {
|
|
|
1617
1876
|
});
|
|
1618
1877
|
}
|
|
1619
1878
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: MaxAssistantComponent, deps: [{ token: MaxAssistantService }, { token: MaxAssistantExportService }, { token: MaxAssistantFeedbackService }, { token: MaxAssistantSupportService }, { token: i0.DestroyRef }, { token: MAX_ASSISTANT_CONFIG }], target: i0.ɵɵFactoryTarget.Component });
|
|
1620
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.14", type: MaxAssistantComponent, isStandalone: true, selector: "max-assistant", inputs: { app: "app", assistantApiUrl: "assistantApiUrl", user: "user", context: "context", requestHeaders: "requestHeaders", developerDetailsEnabled: "developerDetailsEnabled" }, outputs: { hostAction: "hostAction", closeRequested: "closeRequested" }, host: { listeners: { "document:keydown.escape": "onDocumentEscape()" } }, viewQueries: [{ propertyName: "messagesViewport", first: true, predicate: ["messagesViewport"], descendants: true }, { propertyName: "composerInput", first: true, predicate: ["composerInput"], descendants: true }, { propertyName: "supportQueryInput", first: true, predicate: ["supportQueryInput"], descendants: true }, { propertyName: "feedbackInput", first: true, predicate: ["feedbackInput"], descendants: true }], ngImport: i0, template: "<aside\n class=\"assistant-window\"\n [attr.aria-label]=\"uiCopy.title\"\n role=\"region\"\n>\n <section class=\"assistant-panel\">\n <header class=\"assistant-header\">\n <i class=\"max-assistant-sparkles far fa-sparkles\" aria-hidden=\"true\"></i>\n <div class=\"assistant-identity\">\n <div class=\"assistant-name-row\">\n <h2 class=\"assistant-name\">{{ uiCopy.title }}</h2>\n <span class=\"assistant-beta-tag\">Beta</span>\n </div>\n <span class=\"assistant-subtitle\">{{ uiCopy.subtitle }}</span>\n </div>\n <div class=\"assistant-header-actions\">\n <button\n type=\"button\"\n class=\"header-action\"\n [attr.aria-label]=\"uiCopy.clearLabel\"\n [pTooltip]=\"uiCopy.clearTooltip\"\n tooltipPosition=\"bottom\"\n (click)=\"clearChatSession()\"\n >\n <i class=\"header-action-icon pi pi-refresh\" aria-hidden=\"true\"></i>\n </button>\n <button\n type=\"button\"\n class=\"header-action\"\n [attr.aria-label]=\"uiCopy.closeLabel\"\n [pTooltip]=\"uiCopy.closeTooltip\"\n tooltipPosition=\"bottom\"\n (click)=\"requestClose()\"\n >\n <i class=\"header-action-icon pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </header>\n\n <div #messagesViewport class=\"assistant-messages\">\n @for(message of messages(); track message.id) {\n <article\n class=\"message {{ message.role }}\"\n [class.welcome-message]=\"isWelcomeMessage(message)\"\n [class.welcome]=\"isWelcomeState(message)\"\n [class.error]=\"message.isError\"\n [class.streaming]=\"message.isStreaming\"\n [attr.aria-live]=\"message.isStreaming ? 'polite' : null\"\n [attr.aria-busy]=\"message.isStreaming || null\"\n [attr.role]=\"message.isStreaming ? 'status' : null\"\n >\n @if(message.isStreaming) {\n <p class=\"streaming-progress\">{{ message.content }}</p>\n } @else if(message.displayResponse; as responseDetails) {\n @if(responseDetails.markdown || responseDetails.agentInferredResponse || message.content) {\n <div\n class=\"assistant-result assistant-markdown\"\n [innerHTML]=\"(responseDetails.markdown || responseDetails.agentInferredResponse || message.content) | maxAssistantMarkdown\"\n ></div>\n }\n @if(message.cards?.length) {\n <div class=\"assistant-cards\">\n @for(card of message.cards ?? []; track $index) {\n <section class=\"assistant-card\">\n <header>\n <span class=\"assistant-card-title\">{{ card.title }}</span>\n @if(card.subtitle) {\n <span class=\"assistant-card-subtitle\">{{ card.subtitle }}</span>\n }\n </header>\n <div class=\"assistant-card-metrics\">\n @for(metric of card.metrics; track metric.label) {\n <div class=\"assistant-card-metric\" [class.assistant-card-metric-wide]=\"isListMetric(metric)\" [attr.data-tone]=\"metric.tone || 'default'\">\n <span class=\"assistant-card-label\">{{ metric.label }}</span>\n <span class=\"assistant-card-value\">{{ metric.value }}</span>\n </div>\n }\n </div>\n @if(card.footer) {\n <footer>{{ card.footer }}</footer>\n }\n </section>\n }\n </div>\n }\n @if(responseDetails.searchResults?.length) {\n <div class=\"assistant-cards assistant-search-results\" aria-label=\"Search results\">\n @for(result of responseDetails.searchResults ?? []; track $index) {\n <section class=\"assistant-card assistant-search-result\">\n <header>\n <i\n class=\"assistant-search-result-icon\"\n [class]=\"searchResultIcon(result.type)\"\n aria-hidden=\"true\"\n ></i>\n <div class=\"assistant-search-result-copy\">\n <strong>{{ result.title }}</strong>\n <span>{{ result.type }}</span>\n </div>\n </header>\n <div class=\"suggestions\" aria-label=\"Available destinations\">\n @for(action of result.actions; track action.label) {\n <button\n pButton\n type=\"button\"\n size=\"small\"\n severity=\"secondary\"\n class=\"suggestion-chip\"\n [label]=\"action.label\"\n [icon]=\"searchActionIcon(action)\"\n [disabled]=\"isSending()\"\n (click)=\"performHostAction(action.hostAction)\"\n ></button>\n }\n </div>\n </section>\n }\n </div>\n }\n @if(message.pendingAction; as pendingAction) {\n <section class=\"pending-action\" aria-label=\"Cortex action confirmation\">\n <div class=\"pending-action-heading\">\n <strong>Confirmation required</strong>\n <span>{{ pendingAction.method }}</span>\n </div>\n <p>{{ pendingAction.summary }}</p>\n <small>Expires {{ pendingAction.expiresAt | date: 'mediumTime' }}</small>\n @if(message.actionDecision; as actionDecision) {\n <p class=\"action-decision\">\n {{ actionDecision === 'approve' ? 'Approval sent' : 'Rejection sent' }}\n </p>\n } @else {\n <div class=\"pending-action-buttons\">\n <button\n pButton\n type=\"button\"\n size=\"small\"\n severity=\"success\"\n label=\"Approve\"\n [disabled]=\"isSending()\"\n (click)=\"resolvePendingAction(message, 'approve')\"\n ></button>\n <button\n pButton\n type=\"button\"\n size=\"small\"\n outlined\n severity=\"secondary\"\n label=\"Reject\"\n [disabled]=\"isSending()\"\n (click)=\"resolvePendingAction(message, 'reject')\"\n ></button>\n </div>\n }\n </section>\n }\n @if(responseDetails.shiftCardGroups?.length) {\n <div class=\"assistant-shift-groups\" aria-label=\"Team shifts\">\n @for(group of responseDetails.shiftCardGroups ?? []; track group.title) {\n <section class=\"assistant-shift-group\">\n <h3>{{ group.title }}</h3>\n <div class=\"assistant-shift-card-grid\">\n @for(shift of group.shifts; track shift.id || $index) {\n <max-agent-shift-card\n [shift]=\"shift\"\n variant=\"definition\"\n ></max-agent-shift-card>\n }\n </div>\n </section>\n }\n </div>\n }\n @if(responseDetails.rota; as rota) {\n <section class=\"assistant-rota\" [attr.aria-label]=\"rota.title\">\n <div class=\"assistant-rota-heading\">\n <h3>{{ rota.title }}</h3>\n <div class=\"assistant-rota-summary\">\n @if(rota.startDate) {\n <span><small>From</small><strong>{{ rota.startDate }}</strong></span>\n }\n <span><small>Weeks</small><strong>{{ rota.weeksCount }}</strong></span>\n @if(rota.contracted) {\n <span><small>Contracted</small><strong>{{ rota.contracted }}</strong></span>\n }\n @if(rota.autoPublish) {\n <span><small>Auto publish</small><strong>{{ rota.autoPublish }}</strong></span>\n }\n </div>\n </div>\n <div class=\"assistant-rota-scroll\">\n @for(week of rota.weeks; track week.week) {\n <section class=\"assistant-rota-week\">\n <header class=\"assistant-rota-week-heading\">\n <strong>Week {{ week.week }}</strong>\n @if(week.duration) {\n <span>{{ week.duration }}</span>\n }\n </header>\n <div class=\"assistant-rota-week-grid\">\n @for(day of week.days; track day.day) {\n <article class=\"assistant-rota-day\">\n <header>\n <strong>{{ day.label }}</strong>\n @if(day.period) {\n <span>{{ day.period }}</span>\n }\n </header>\n <div class=\"assistant-rota-day-shifts\">\n @for(shift of day.shifts; track shift.id || $index) {\n <max-agent-shift-card\n [shift]=\"shift\"\n variant=\"rota\"\n ></max-agent-shift-card>\n } @empty {\n <span class=\"assistant-rota-empty\">No shifts</span>\n }\n </div>\n </article>\n }\n </div>\n </section>\n } @empty {\n <p class=\"assistant-rota-no-weeks\">No rota weeks were returned.</p>\n }\n </div>\n </section>\n }\n @if(responseDetails.visualisations?.length) {\n <div class=\"assistant-visualisations\">\n @for(visualisation of responseDetails.visualisations ?? []; track visualisation.title) {\n <section class=\"assistant-visualisation\">\n <header class=\"assistant-export-heading\">\n <h3>{{ visualisation.title }}</h3>\n <button\n pButton\n type=\"button\"\n size=\"small\"\n severity=\"secondary\"\n class=\"assistant-export-action assistant-export-action-pdf\"\n icon=\"pi pi-file-pdf\"\n [attr.aria-label]=\"'Export ' + visualisation.title + ' as PDF'\"\n (click)=\"exportVisualisation(visualisation)\"\n ></button>\n </header>\n @if(visualisation.type === 'doughnut') {\n <div class=\"assistant-doughnut-layout\">\n <div\n class=\"assistant-doughnut\"\n role=\"img\"\n [attr.aria-label]=\"chartAriaLabel(visualisation)\"\n >\n <svg viewBox=\"0 0 42 42\" aria-hidden=\"true\" focusable=\"false\">\n <circle\n class=\"assistant-doughnut-track\"\n cx=\"21\"\n cy=\"21\"\n r=\"15.9155\"\n ></circle>\n @for(value of visualisation.values; track $index; let valueIndex = $index) {\n <circle\n class=\"assistant-doughnut-segment\"\n cx=\"21\"\n cy=\"21\"\n r=\"15.9155\"\n pathLength=\"100\"\n [attr.stroke]=\"chartColor(visualisation, valueIndex)\"\n [attr.stroke-dasharray]=\"doughnutDashArray(visualisation, valueIndex)\"\n [attr.stroke-dashoffset]=\"doughnutDashOffset(visualisation, valueIndex)\"\n ></circle>\n }\n </svg>\n <span><strong>{{ chartTotal(visualisation) }}</strong>{{ visualisation.valueLabel || 'people' }}</span>\n </div>\n <div class=\"assistant-chart-legend\">\n @for(label of visualisation.labels; track $index; let labelIndex = $index) {\n <div class=\"assistant-chart-legend-item\">\n <i [style.background]=\"chartColor(visualisation, labelIndex)\"></i>\n <span>{{ label }}</span>\n <strong>{{ visualisation.values[labelIndex] || 0 }}</strong>\n </div>\n }\n </div>\n </div>\n } @else {\n <div\n class=\"assistant-bar-chart\"\n role=\"img\"\n [attr.aria-label]=\"chartAriaLabel(visualisation)\"\n >\n @for(label of visualisation.labels; track $index; let labelIndex = $index) {\n <div class=\"assistant-bar-row\">\n <div class=\"assistant-bar-label\">\n <span>{{ label }}</span>\n <strong>{{ visualisation.values[labelIndex] || 0 }}</strong>\n </div>\n <div class=\"assistant-bar-track\" aria-hidden=\"true\">\n <i\n [style.width.%]=\"barWidth(visualisation, labelIndex)\"\n [style.background]=\"chartColor(visualisation, labelIndex)\"\n ></i>\n </div>\n </div>\n }\n </div>\n }\n </section>\n }\n </div>\n }\n @if(getResponseGrid(responseDetails).length) {\n <div class=\"assistant-tables\">\n @for(table of getResponseGrid(responseDetails); track $index) {\n <section class=\"assistant-table-section\">\n <header class=\"assistant-export-heading\">\n @if(table.title) {\n <h3>{{ table.title }}</h3>\n }\n <button\n pButton\n type=\"button\"\n size=\"small\"\n severity=\"secondary\"\n class=\"assistant-export-action assistant-export-action-excel\"\n icon=\"pi pi-file-excel\"\n [attr.aria-label]=\"'Export ' + (table.title || 'results') + ' to Excel'\"\n (click)=\"exportTable(table)\"\n ></button>\n </header>\n <div class=\"assistant-table-wrap\">\n <table>\n <thead>\n <tr>\n @for(column of table.columns; track column.field) {\n <th>{{ column.header }}</th>\n }\n @if(table.actions?.length) {\n <th>Actions</th>\n }\n </tr>\n </thead>\n <tbody>\n @for(row of table.rows; track $index; let rowIndex = $index) {\n <tr>\n @for(column of table.columns; track column.field) {\n <td>{{ row[column.field] }}</td>\n }\n @if(table.actions?.length) {\n <td>\n <div class=\"assistant-table-actions\">\n @for(action of getTableRowActions(table, rowIndex); track action.label) {\n <button\n pButton\n type=\"button\"\n size=\"small\"\n [severity]=\"action.tone || 'secondary'\"\n [outlined]=\"action.tone === 'danger'\"\n [label]=\"action.label\"\n [disabled]=\"isSending()\"\n (click)=\"useTableAction(action)\"\n ></button>\n }\n </div>\n </td>\n }\n </tr>\n }\n </tbody>\n </table>\n </div>\n </section>\n }\n </div>\n }\n @if(message.sources?.length) {\n <div class=\"assistant-sources\">\n <strong>Sources</strong>\n @for(source of message.sources ?? []; track source.citation) {\n <span>{{ source.citation }}</span>\n }\n </div>\n }\n @if(developerDetailsEnabled && message.developerTrace?.steps?.length) {\n @if(isDetailsVisible(message.id)) {\n <div class=\"details-dialog-backdrop\" (click)=\"toggleDetails(message.id)\">\n <section\n class=\"developer-details\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"Agent processing details\"\n (click)=\"$event.stopPropagation()\"\n >\n <header class=\"developer-details-header\">\n <div>\n <span class=\"developer-eyebrow\">Developer trace</span>\n <h3>How this request was processed</h3>\n <p>A technical, step-by-step account of routing, inference, tools and results.</p>\n </div>\n <div class=\"details-dialog-actions\">\n <button\n type=\"button\"\n class=\"details-dialog-close\"\n aria-label=\"Close processing details\"\n (click)=\"toggleDetails(message.id)\"\n >\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </header>\n\n @if(message.developerTrace!.run; as run) {\n <section class=\"trace-run-summary\" aria-label=\"Run summary\">\n <div class=\"trace-metric\"><span>Total runtime</span><strong>{{ run.durationMs }} ms</strong></div>\n <div class=\"trace-metric\"><span>Model calls</span><strong>{{ run.llmCalls }}</strong></div>\n <div class=\"trace-metric\"><span>Embedding calls</span><strong>{{ run.embeddingCalls }}</strong></div>\n <div class=\"trace-metric\"><span>API calls</span><strong>{{ run.apiCalls }}</strong></div>\n <div class=\"trace-loop-policy\">\n <div>\n <span>Execution architecture</span>\n <strong>Deterministic step pipeline</strong>\n </div>\n <span class=\"trace-no-loop\">No autonomous model loop</span>\n <p>{{ run.loopPolicy }}</p>\n </div>\n </section>\n }\n\n <ol class=\"workflow-trace\">\n @for(step of message.developerTrace!.steps; track step.id; let stepIndex = $index) {\n <li class=\"workflow-step\" [attr.data-status]=\"traceStepTone(step)\">\n <section class=\"workflow-section\">\n <button\n type=\"button\"\n class=\"workflow-step-toggle\"\n [attr.aria-expanded]=\"isTraceStepExpanded(message.id, step.id)\"\n (click)=\"toggleTraceStep(message.id, step.id)\"\n >\n <div>\n <span class=\"workflow-step-number\">Step {{ stepIndex + 1 }}</span>\n <h4>{{ step.title }}</h4>\n <span class=\"workflow-category\">{{ formatTraceCategory(step.category) }}</span>\n </div>\n <div class=\"workflow-meta\">\n <span class=\"workflow-status\">{{ traceStepStatus(step) }}</span>\n @if(step.durationMs !== undefined) {\n <span>{{ step.durationMs }} ms</span>\n }\n <i\n class=\"pi workflow-expand-icon\"\n [class.pi-chevron-down]=\"isTraceStepExpanded(message.id, step.id)\"\n [class.pi-chevron-right]=\"!isTraceStepExpanded(message.id, step.id)\"\n aria-hidden=\"true\"\n ></i>\n </div>\n </button>\n\n @if(isTraceStepExpanded(message.id, step.id)) {\n <div class=\"workflow-step-content\">\n @if(step.metadata?.summary) {\n <p class=\"workflow-summary\">{{ step.metadata!.summary }}</p>\n }\n\n @if(step.metadata?.technology; as technology) {\n <div class=\"trace-technology\">\n <span class=\"trace-section-label\">Technology</span>\n <div class=\"trace-inline-facts\">\n <span><small>Component</small>{{ technology.component }}</span>\n @if(technology.model) { <span><small>Model</small>{{ technology.model }}</span> }\n @if(technology.library) { <span><small>Library</small>{{ technology.library }}</span> }\n @if(technology.provider) { <span><small>Provider</small>{{ technology.provider }}</span> }\n @if(technology.operation) { <span><small>Operation</small>{{ technology.operation }}</span> }\n </div>\n </div>\n }\n\n @if(step.metadata?.control; as control) {\n <div class=\"trace-control\">\n <div>\n <span class=\"trace-section-label\">Stop control</span>\n <strong>{{ formatTraceLabel(control.mode) }}</strong>\n </div>\n @if(control.maximumIterations !== undefined) {\n <span>{{ control.iterationsUsed ?? 0 }} / {{ control.maximumIterations }} iteration</span>\n }\n <p>{{ control.stopCondition }}</p>\n </div>\n }\n\n @switch(step.category) {\n @case('request') {\n @if(traceField(step.input, 'userQuery'); as userQuery) {\n <div class=\"trace-query\">\n <span>Original user query</span>\n <blockquote>{{ formatTraceScalar(userQuery) }}</blockquote>\n </div>\n }\n <div class=\"trace-card-grid\">\n @for(group of [\n { label: 'Product', value: traceMapField(step.input, 'product') },\n { label: 'User', value: traceMapField(step.input, 'user') },\n { label: 'Request context', value: traceMapField(step.input, 'requestContext') },\n { label: 'Conversation', value: traceMapField(step.input, 'conversation') },\n { label: 'Live API context', value: traceMapField(step.input, 'liveApi') }\n ]; track group.label) {\n @if(group.value) {\n <section class=\"trace-data-card\">\n <h5>{{ group.label }}</h5>\n <dl class=\"trace-field-list\">\n @for(entry of traceEntries(group.value, group.label === 'User' ? ['permissions'] : []); track entry.key) {\n <div><dt>{{ entry.label }}</dt><dd>{{ formatTraceScalar(entry.value) }}</dd></div>\n }\n </dl>\n </section>\n }\n }\n </div>\n }\n\n @case('intent_projection') {\n <div class=\"trace-transform\">\n <div>\n <span>Original query</span>\n <p>{{ formatTraceScalar(traceField(step.output, 'originalUserQuery') ?? traceField(step.input, 'originalUserQuery')) }}</p>\n </div>\n <span class=\"trace-transform-arrow\" aria-hidden=\"true\">\u2192</span>\n <div class=\"trace-transform-result\">\n <span>Generalised intent sent to embedding</span>\n <p>{{ formatTraceScalar(traceField(step.output, 'generalisedIntent') ?? traceField(step.output, 'routingText')) }}</p>\n </div>\n </div>\n @if(traceArrayField(step.output, 'removedArguments').length) {\n <div class=\"trace-section\">\n <span class=\"trace-section-label\">Arguments removed before routing</span>\n <div class=\"trace-entity-list\">\n @for(argument of traceArrayField(step.output, 'removedArguments'); track $index) {\n <span><small>{{ formatTraceScalar(traceField(argument, 'kind')) }}</small>{{ formatTraceScalar(traceField(argument, 'value')) }}</span>\n }\n </div>\n </div>\n }\n }\n\n @case('embedding') {\n <div class=\"trace-query trace-query-compact\">\n <span>Embedded text</span>\n <blockquote>{{ formatTraceScalar(traceField(step.input, 'generalisedIntent')) }}</blockquote>\n </div>\n <div class=\"trace-stat-grid\">\n <div><span>Embedding model</span><strong>{{ formatTraceScalar(traceField(step.output, 'model') ?? traceField(step.input, 'model')) }}</strong></div>\n <div><span>Dimensions</span><strong>{{ formatTraceScalar(traceField(step.output, 'dimensions')) }}</strong></div>\n <div><span>Vector magnitude</span><strong>{{ formatTraceScalar(traceField(step.output, 'vectorMagnitude')) }}</strong></div>\n <div><span>Full vector exposed</span><strong>{{ formatTraceScalar(traceField(step.output, 'fullVectorShown')) }}</strong></div>\n </div>\n @if(traceField(step.output, 'vectorPreview'); as vectorPreview) {\n <div class=\"trace-vector\">\n <span>Vector preview</span>\n <code>{{ formatTraceScalar(vectorPreview) }}</code>\n </div>\n }\n }\n\n @case('capability_routing') {\n @if(traceMapField(step.output, 'routing'); as routing) {\n <div class=\"trace-supabase-call\">\n <div><span>Routing strategy</span><strong>{{ formatTraceScalar(traceField(routing, 'strategy')) }}</strong></div>\n <div><span>Cache status</span><strong>{{ formatTraceScalar(traceField(routing, 'cacheStatus')) }}</strong></div>\n <div><span>Supabase RPC executed</span><strong>{{ formatTraceScalar(traceField(routing, 'supabaseRpcExecuted')) }}</strong></div>\n <div><span>Vector search executed</span><strong>{{ formatTraceScalar(traceField(routing, 'vectorSearchExecuted')) }}</strong></div>\n @if(traceField(routing, 'supabaseRpcExecuted')) {\n <div><span>Supabase RPC</span><strong>{{ formatTraceScalar(traceField(routing, 'rpc')) }}</strong></div>\n <div><span>Database</span><strong>{{ formatTraceScalar(traceField(routing, 'database')) }}</strong></div>\n @if(traceArrayField(routing, 'tables').length) {\n <div class=\"trace-table-list\">\n <span>Tables searched</span>\n <div>\n @for(table of traceArrayField(routing, 'tables'); track $index) {\n <code>{{ formatTraceScalar(table) }}</code>\n }\n </div>\n </div>\n }\n }\n </div>\n } @else {\n <div class=\"trace-supabase-call\">\n <div><span>Supabase RPC</span><strong>{{ formatTraceScalar(traceField(step.input, 'rpc')) }}</strong></div>\n <div><span>Database</span><strong>{{ formatTraceScalar(traceField(step.input, 'database')) }}</strong></div>\n @if(traceArrayField(step.input, 'tables').length) {\n <div class=\"trace-table-list\">\n <span>Tables searched</span>\n <div>\n @for(table of traceArrayField(step.input, 'tables'); track $index) {\n <code>{{ formatTraceScalar(table) }}</code>\n }\n </div>\n </div>\n }\n </div>\n }\n @if(traceMapField(step.output, 'decision'); as decision) {\n <section class=\"trace-decision\">\n <span>Routing decision</span>\n <strong>{{ formatTraceScalar(decision['selectedCapabilityLabel'] ?? decision['selectedCapabilityKey']) }}</strong>\n <div>\n <span>Status: {{ formatTraceScalar(decision['status']) }}</span>\n <span>Confidence: {{ formatSimilarity(decision['confidence']) }}</span>\n <span>Runner-up: {{ formatSimilarity(decision['runnerUpConfidence']) }}</span>\n </div>\n </section>\n }\n @if(traceArrayField(step.output, 'matchedCapabilities').length) {\n <div class=\"trace-ranking-wrap\">\n <span class=\"trace-section-label\">Ranked capability matches</span>\n <table class=\"trace-ranking\">\n <thead><tr><th>#</th><th>Capability</th><th>Combined</th><th>Semantic</th><th>Definition</th><th>Example</th><th>Keyword</th></tr></thead>\n <tbody>\n @for(candidate of traceArrayField(step.output, 'matchedCapabilities'); track $index) {\n <tr>\n <td>{{ formatTraceScalar(traceField(candidate, 'rank')) }}</td>\n <td><strong>{{ formatTraceScalar(traceField(candidate, 'label')) }}</strong><code>{{ formatTraceScalar(traceField(candidate, 'capabilityKey')) }}</code></td>\n <td>{{ formatSimilarity(traceField(candidate, 'combinedScore')) }}</td>\n <td>{{ formatSimilarity(traceField(candidate, 'semanticScore')) }}</td>\n <td>{{ formatSimilarity(traceField(candidate, 'definitionScore')) }}</td>\n <td>{{ formatSimilarity(traceField(candidate, 'exampleScore')) }}</td>\n <td>{{ formatSimilarity(traceField(candidate, 'keywordScore')) }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n }\n\n @case('argument_extraction') {\n <div class=\"trace-card-grid\">\n @if(traceMapField(step.output, 'selectedCapability') ?? traceMapField(step.input, 'selectedCapability'); as capability) {\n <section class=\"trace-data-card trace-data-card-accent\">\n <h5>Selected capability</h5>\n <dl class=\"trace-field-list\">\n @for(entry of traceEntries(capability); track entry.key) {\n <div><dt>{{ entry.label }}</dt><dd>{{ formatTraceScalar(entry.value) }}</dd></div>\n }\n </dl>\n </section>\n }\n @if(traceMapField(step.input, 'tool'); as tool) {\n <section class=\"trace-data-card\">\n <h5>Allowlisted tool</h5>\n <dl class=\"trace-field-list\">\n @for(entry of traceEntries(tool); track entry.key) {\n <div><dt>{{ entry.label }}</dt><dd>{{ formatTraceScalar(entry.value) }}</dd></div>\n }\n </dl>\n </section>\n }\n </div>\n @if(traceMapField(step.output, 'extractedArguments'); as arguments) {\n <section class=\"trace-arguments\">\n <span class=\"trace-section-label\">Arguments extracted from the original query</span>\n <dl class=\"trace-argument-grid\">\n @for(entry of traceEntries(arguments); track entry.key) {\n <div><dt>{{ entry.label }}</dt><dd>{{ formatTraceScalar(entry.value) }}</dd></div>\n }\n </dl>\n </section>\n }\n @if(traceMapField(step.output, 'plannedToolCall'); as plannedCall) {\n <div class=\"trace-tool-call\">\n <span>Planned tool call</span>\n <strong>{{ formatTraceScalar(plannedCall['method']) }} \u00B7 {{ formatTraceScalar(plannedCall['toolName']) }}</strong>\n <pre>{{ formatTraceValue(plannedCall['arguments']) }}</pre>\n </div>\n }\n }\n\n @case('api_call') {\n @if(traceField(step.input, 'sql'); as sql) {\n <div class=\"trace-tool-call trace-sql-query\">\n <span>SQL sent to MySQL MCP</span>\n <strong>{{ formatTraceScalar(traceField(step.input, 'toolName')) }}</strong>\n <pre>{{ formatTraceScalar(sql) }}</pre>\n </div>\n }\n @if(traceField(step.input, 'method') || traceField(step.input, 'path')) {\n <div class=\"trace-api-route\">\n <span class=\"trace-http-method\">{{ formatTraceScalar(traceField(step.input, 'method')) }}</span>\n <code>{{ formatTraceScalar(traceField(step.input, 'path')) }}</code>\n @if(getHttpStatus(step); as statusCode) {\n <span class=\"trace-http-status\" [class.success]=\"isHttpSuccessful(step)\" [class.error]=\"!isHttpSuccessful(step)\">\n HTTP {{ statusCode }} \u00B7 {{ isHttpSuccessful(step) ? 'Success' : 'Error' }}\n </span>\n }\n </div>\n }\n <div class=\"trace-payload-grid\">\n @if(traceField(step.input, 'body'); as requestBody) {\n <section><span>Request payload</span><pre>{{ formatTraceValue(requestBody) }}</pre></section>\n }\n @if(traceField(step.output, 'response'); as apiResponse) {\n <section><span>API response</span><pre>{{ formatTraceValue(apiResponse) }}</pre></section>\n }\n @if(traceField(step.input, 'sql') && step.output !== undefined) {\n <section><span>MySQL MCP execution details</span><pre>{{ formatTraceValue(step.output) }}</pre></section>\n }\n </div>\n }\n\n @case('action') {\n <div class=\"trace-card-grid\">\n <section class=\"trace-data-card\">\n <h5>Workflow input</h5>\n <dl class=\"trace-field-list\">\n @for(entry of traceEntries(step.input); track entry.key) {\n <div><dt>{{ entry.label }}</dt><dd>{{ formatTraceScalar(entry.value) }}</dd></div>\n }\n </dl>\n </section>\n <section class=\"trace-data-card trace-data-card-accent\">\n <h5>Outcome</h5>\n <dl class=\"trace-field-list\">\n @for(entry of traceEntries(step.output); track entry.key) {\n <div><dt>{{ entry.label }}</dt><dd>{{ formatTraceScalar(entry.value) }}</dd></div>\n }\n </dl>\n </section>\n </div>\n }\n\n @case('response') {\n @if(traceField(step.output, 'answer'); as answer) {\n <div class=\"trace-query\"><span>Final grounded response</span><blockquote>{{ formatTraceScalar(answer) }}</blockquote></div>\n }\n <dl class=\"trace-argument-grid\">\n @for(entry of traceEntries(step.output); track entry.key) {\n @if(entry.key !== 'answer') {\n <div><dt>{{ entry.label }}</dt><dd>{{ formatTraceScalar(entry.value) }}</dd></div>\n }\n }\n </dl>\n }\n\n @default {\n <div class=\"trace-payload-grid\">\n @if(step.input !== undefined) {\n <section><span>Input</span><pre>{{ formatTraceValue(step.input) }}</pre></section>\n }\n @if(step.output !== undefined) {\n <section><span>Output</span><pre>{{ formatTraceValue(step.output) }}</pre></section>\n }\n </div>\n }\n }\n\n @if(step.error; as error) {\n <div class=\"trace-error\" [class.trace-warning]=\"step.category === 'api_call' && isHttpSuccessful(step)\">\n <strong class=\"trace-error-heading\">\n @if(step.category === 'api_call' && isHttpSuccessful(step)) {\n Post-response processing stopped\n } @else {\n Step stopped@if(error.statusCode) { \u00B7 HTTP {{ error.statusCode }} }\n }\n </strong>\n <strong class=\"trace-error-legacy\" aria-hidden=\"true\">\n Failed@if(error.statusCode) { \u2014 HTTP {{ error.statusCode }} }\n </strong>\n <span>{{ error.message }}</span>\n </div>\n }\n </div>\n }\n </section>\n </li>\n }\n </ol>\n </section>\n </div>\n }\n }\n } @else {\n @if(message.role === 'assistant') {\n <div\n class=\"assistant-markdown\"\n [innerHTML]=\"message.content | maxAssistantMarkdown\"\n ></div>\n @if(isWelcomeState(message) && bootstrapConfig.initialDescription; as initialDescription) {\n <p class=\"welcome-description\">{{ initialDescription }}</p>\n }\n @if(isWelcomeState(message)) {\n <button\n type=\"button\"\n class=\"support-welcome-card\"\n aria-label=\"Raise a support ticket\"\n (click)=\"openSupportTicket()\"\n >\n <span class=\"support-welcome-icon\" aria-hidden=\"true\">\n <i class=\"far fa-user-headset\"></i>\n </span>\n <span class=\"support-welcome-copy\">\n <strong>Raise a support ticket</strong>\n <small>Send details directly to our support team.</small>\n </span>\n <i class=\"support-welcome-arrow pi pi-arrow-right\" aria-hidden=\"true\"></i>\n </button>\n }\n } @else {\n <p>{{ message.content }}</p>\n }\n }\n @if(message.role === 'assistant' && message.suggestions?.length) {\n @if(hasCapabilitySuggestions(message.suggestions)) {\n <div class=\"capability-options\" aria-label=\"Available Maxtime capabilities\">\n @for(group of capabilitySuggestionGroups(message.suggestions); track group.section) {\n <section class=\"capability-option-section\">\n <h3>{{ group.section }}</h3>\n <div class=\"capability-option-grid\">\n @for(suggestion of group.options; track suggestion.structuredAction?.capabilityKey ?? suggestion.label; let optionIndex = $index) {\n <button\n pButton\n type=\"button\"\n severity=\"secondary\"\n class=\"capability-option-card\"\n [disabled]=\"isSending()\"\n [attr.aria-label]=\"'Choose capability: ' + suggestion.label\"\n (click)=\"useSuggestion(suggestion)\"\n >\n <span class=\"capability-option-number\" aria-hidden=\"true\">\n {{ optionIndex + 1 }}\n </span>\n <span class=\"capability-option-copy\">{{ suggestion.label }}</span>\n <i class=\"pi pi-arrow-right capability-option-arrow\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n </section>\n }\n </div>\n } @else if(hasOptionCardSuggestions(message.suggestions, message.status)) {\n <div class=\"clarification-options\" aria-label=\"Clarification options\">\n <div class=\"capability-option-grid clarification-option-grid\">\n @for(suggestion of optionCardSuggestions(message.suggestions, message.status); track suggestionLabel(suggestion); let optionIndex = $index) {\n <button\n pButton\n type=\"button\"\n severity=\"secondary\"\n class=\"capability-option-card clarification-option-card\"\n [disabled]=\"isSending()\"\n [attr.aria-label]=\"'Choose option: ' + suggestionLabel(suggestion)\"\n (click)=\"useSuggestion(suggestion)\"\n >\n <span class=\"capability-option-number\" aria-hidden=\"true\">\n {{ optionIndex + 1 }}\n </span>\n <span class=\"capability-option-copy\">{{ suggestionLabel(suggestion) }}</span>\n <i class=\"pi pi-arrow-right capability-option-arrow\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n </div>\n } @else if(hasEntitySuggestions(message.suggestions)) {\n <div class=\"entity-options\" aria-label=\"Matching options\">\n @for(suggestion of entitySuggestionOptions(message.suggestions); track suggestion.entity.id ?? suggestion.label) {\n <max-agent-entity-option\n [entity]=\"suggestion.entity\"\n [disabled]=\"isSending()\"\n (selected)=\"useSuggestion(suggestion)\"\n ></max-agent-entity-option>\n }\n </div>\n } @else {\n <div class=\"suggestions\">\n @for(suggestion of message.suggestions ?? []; track suggestion) {\n <button\n pButton\n type=\"button\"\n size=\"small\"\n text\n severity=\"secondary\"\n class=\"suggestion-chip\"\n [label]=\"suggestionLabel(suggestion)\"\n (click)=\"useSuggestion(suggestion)\"\n ></button>\n }\n </div>\n }\n }\n @if(message.role === 'assistant' && !isWelcomeMessage(message) && !message.isStreaming) {\n <div class=\"response-actions\">\n <button\n type=\"button\"\n class=\"response-feedback-action\"\n [attr.aria-label]=\"uiCopy.feedbackLabel\"\n [pTooltip]=\"uiCopy.feedbackTooltip\"\n tooltipPosition=\"bottom\"\n (click)=\"openFeedback(message)\"\n >\n <i class=\"pi pi-comment\" aria-hidden=\"true\"></i>\n </button>\n @if(developerDetailsEnabled && message.developerTrace?.steps?.length) {\n <button\n type=\"button\"\n class=\"details-toggle\"\n [attr.aria-expanded]=\"isDetailsVisible(message.id)\"\n (click)=\"toggleDetails(message.id, message.developerTrace!.steps[0]?.id)\"\n >\n {{ isDetailsVisible(message.id) ? 'Hide Developer Trace' : 'Show Developer Trace' }}\n </button>\n }\n </div>\n }\n </article>\n }\n </div>\n\n <footer class=\"assistant-footer\">\n @if(hasConversationStarted()) {\n <button\n type=\"button\"\n class=\"support-ticket-shortcut\"\n aria-label=\"Raise a support ticket\"\n (click)=\"openSupportTicket()\"\n >\n <i class=\"far fa-user-headset\" aria-hidden=\"true\"></i>\n <span>Raise a support ticket</span>\n </button>\n }\n <form class=\"assistant-composer\" (ngSubmit)=\"sendMessage()\">\n <textarea\n #composerInput\n pTextarea\n name=\"assistantPrompt\"\n rows=\"1\"\n [placeholder]=\"uiCopy.placeholder\"\n [ngModel]=\"input()\"\n (ngModelChange)=\"input.set($event)\"\n (keydown)=\"onComposerKeydown($event)\"\n >\n </textarea>\n <button\n pButton\n type=\"submit\"\n icon=\"pi pi-send\"\n aria-label=\"Send message\"\n [disabled]=\"!input().trim() || isSending()\"\n ></button>\n </form>\n </footer>\n </section>\n\n @if(supportTicketVisible()) {\n <section class=\"support-ticket-overlay\" aria-label=\"Support ticket form\">\n <div\n class=\"support-ticket-dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"supportTicketTitle\"\n >\n <header class=\"support-ticket-header\">\n <span class=\"support-ticket-header-icon\" aria-hidden=\"true\">\n <i class=\"far fa-user-headset\"></i>\n </span>\n <div>\n <h2 id=\"supportTicketTitle\">Raise a support ticket</h2>\n <p>Share the details and our support team will take it from here.</p>\n </div>\n <button\n type=\"button\"\n class=\"support-ticket-close\"\n aria-label=\"Close support ticket form\"\n (click)=\"closeSupportTicket()\"\n >\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </header>\n\n @if(supportTicketResult(); as result) {\n <div class=\"support-ticket-success\" role=\"status\">\n <span class=\"support-ticket-success-icon\" aria-hidden=\"true\">\n <i class=\"pi pi-check\"></i>\n </span>\n <h3>Ticket raised</h3>\n <p>{{ result.message }}</p>\n <div class=\"support-ticket-reference\">\n <span>Reference</span>\n <strong>{{ result.ticketReference }}</strong>\n </div>\n <button\n pButton\n type=\"button\"\n label=\"Done\"\n icon=\"pi pi-check\"\n (click)=\"closeSupportTicket()\"\n ></button>\n </div>\n } @else {\n <form class=\"support-ticket-form\" (ngSubmit)=\"submitSupportTicket()\">\n <div class=\"support-ticket-fields\">\n <label class=\"support-ticket-field\">\n <span>Name</span>\n <input\n type=\"text\"\n name=\"supportName\"\n autocomplete=\"name\"\n [value]=\"supportTicketForm.name\"\n readonly\n />\n </label>\n\n <label class=\"support-ticket-field\">\n <span>Email</span>\n <input\n type=\"email\"\n name=\"supportEmail\"\n autocomplete=\"email\"\n [value]=\"supportTicketForm.email\"\n readonly\n />\n </label>\n\n <label class=\"support-ticket-field support-ticket-field-wide\">\n <span>Phone <small>Optional</small></span>\n <input\n type=\"tel\"\n name=\"supportPhone\"\n autocomplete=\"tel\"\n placeholder=\"Add a contact number\"\n [(ngModel)]=\"supportTicketForm.phone\"\n />\n </label>\n\n <label class=\"support-ticket-field\">\n <span>Severity</span>\n <p-select\n inputId=\"supportSeverity\"\n name=\"supportSeverity\"\n [options]=\"supportSeverityOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [fluid]=\"true\"\n [(ngModel)]=\"supportTicketForm.severity\"\n >\n <ng-template #selectedItem let-severity>\n <p-tag\n class=\"support-severity-tag\"\n [value]=\"severity.label\"\n [severity]=\"severity.severity\"\n [rounded]=\"true\"\n ></p-tag>\n </ng-template>\n <ng-template #item let-severity>\n <p-tag\n class=\"support-severity-option\"\n [value]=\"severity.label\"\n [severity]=\"severity.severity\"\n [rounded]=\"true\"\n ></p-tag>\n </ng-template>\n </p-select>\n </label>\n\n <label class=\"support-ticket-field\">\n <span>Tags</span>\n <p-multiselect\n inputId=\"supportTags\"\n name=\"supportTags\"\n placeholder=\"Select relevant areas\"\n [options]=\"supportTags()\"\n optionLabel=\"label\"\n optionValue=\"value\"\n display=\"chip\"\n [filter]=\"true\"\n filterBy=\"label\"\n [showToggleAll]=\"false\"\n [loading]=\"supportTagsLoading()\"\n [fluid]=\"true\"\n [(ngModel)]=\"supportTicketForm.tags\"\n >\n <ng-template #selecteditems let-selectedTags>\n <span class=\"support-selected-tags\">\n @for(tag of selectedTags; track tag.value) {\n <p-tag\n class=\"support-selected-tag\"\n [value]=\"tag.label\"\n [icon]=\"tag.icon\"\n [severity]=\"tag.severity\"\n [rounded]=\"true\"\n ></p-tag>\n }\n </span>\n </ng-template>\n <ng-template #item let-tag>\n <p-tag\n class=\"support-tag-option\"\n [value]=\"tag.label\"\n [icon]=\"tag.icon\"\n [severity]=\"tag.severity\"\n [rounded]=\"true\"\n ></p-tag>\n </ng-template>\n </p-multiselect>\n </label>\n\n <label class=\"support-ticket-field support-ticket-field-wide\">\n <span>Subject</span>\n <input\n type=\"text\"\n name=\"supportSubject\"\n maxlength=\"200\"\n placeholder=\"Summarise the issue\"\n required\n [(ngModel)]=\"supportTicketForm.subject\"\n />\n </label>\n\n <label class=\"support-ticket-field support-ticket-field-wide\">\n <span>How can we help?</span>\n <textarea\n #supportQueryInput\n pTextarea\n name=\"supportQuery\"\n rows=\"5\"\n placeholder=\"Describe the issue, what you expected, and anything you've already tried.\"\n required\n [(ngModel)]=\"supportTicketForm.query\"\n ></textarea>\n </label>\n </div>\n\n @if(!supportTicketForm.name || !supportTicketForm.email) {\n <p class=\"support-ticket-notice\" role=\"alert\">\n Your signed-in name and email are required. Please refresh your Nemesys session and try again.\n </p>\n }\n @if(supportTicketError(); as supportError) {\n <p class=\"support-ticket-error\" role=\"alert\">{{ supportError }}</p>\n }\n\n <div class=\"support-ticket-actions\">\n <button\n pButton\n type=\"button\"\n label=\"Cancel\"\n severity=\"secondary\"\n outlined\n (click)=\"closeSupportTicket()\"\n ></button>\n <button\n pButton\n type=\"submit\"\n label=\"Submit ticket\"\n icon=\"pi pi-send\"\n [loading]=\"supportTicketSubmitting()\"\n [disabled]=\"!canSubmitSupportTicket()\"\n ></button>\n </div>\n </form>\n }\n </div>\n </section>\n }\n\n @if(feedbackVisible()) {\n <section\n class=\"support-ticket-overlay feedback-overlay\"\n aria-label=\"Feedback form\"\n >\n <div\n class=\"support-ticket-dialog feedback-dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"feedbackTitle\"\n >\n <header class=\"support-ticket-header feedback-header\">\n <span class=\"support-ticket-header-icon\" aria-hidden=\"true\">\n <i class=\"pi pi-comment\"></i>\n </span>\n <div>\n <h2 id=\"feedbackTitle\">Help Max improve</h2>\n <p>Tell us what Max could do better.</p>\n </div>\n <button\n type=\"button\"\n class=\"support-ticket-close feedback-close\"\n aria-label=\"Close feedback form\"\n (click)=\"closeFeedback()\"\n >\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </header>\n\n @if(feedbackResult(); as result) {\n <div class=\"support-ticket-success feedback-success\" role=\"status\">\n <span class=\"support-ticket-success-icon\" aria-hidden=\"true\">\n <i class=\"pi pi-check\"></i>\n </span>\n <h3>Feedback received</h3>\n <p>{{ result.message }}</p>\n <div class=\"support-ticket-reference\">\n <span>Reference</span>\n <strong>{{ result.feedbackReference }}</strong>\n </div>\n <button\n pButton\n type=\"button\"\n label=\"Done\"\n icon=\"pi pi-check\"\n (click)=\"closeFeedback()\"\n ></button>\n </div>\n } @else {\n <form class=\"support-ticket-form feedback-form\" (ngSubmit)=\"submitFeedback()\">\n <div class=\"feedback-form-body\">\n <div class=\"support-ticket-fields\">\n <label class=\"support-ticket-field\">\n <span>Name</span>\n <input\n type=\"text\"\n name=\"feedbackName\"\n autocomplete=\"name\"\n [value]=\"feedbackForm.name\"\n readonly\n />\n </label>\n\n <label class=\"support-ticket-field\">\n <span>Email</span>\n <input\n type=\"email\"\n name=\"feedbackEmail\"\n autocomplete=\"email\"\n [value]=\"feedbackForm.email\"\n readonly\n />\n </label>\n\n <label class=\"support-ticket-field\">\n <span>Phone <small>Optional</small></span>\n <input\n type=\"tel\"\n name=\"feedbackPhone\"\n autocomplete=\"tel\"\n placeholder=\"Add a contact number\"\n [(ngModel)]=\"feedbackForm.phone\"\n />\n </label>\n\n <label class=\"support-ticket-field\">\n <span>Feedback type</span>\n <p-select\n inputId=\"feedbackCategory\"\n name=\"feedbackCategory\"\n [options]=\"feedbackCategoryOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [fluid]=\"true\"\n [(ngModel)]=\"feedbackForm.category\"\n ></p-select>\n </label>\n\n <label class=\"support-ticket-field support-ticket-field-wide\">\n <span>Your query</span>\n <textarea\n pTextarea\n name=\"feedbackQuery\"\n rows=\"2\"\n placeholder=\"Enter the question or request you gave Max.\"\n readonly\n required\n [(ngModel)]=\"feedbackForm.query\"\n ></textarea>\n </label>\n\n <label class=\"support-ticket-field support-ticket-field-wide\">\n <span>Assistant response <small>Added automatically when available</small></span>\n <textarea\n pTextarea\n name=\"feedbackAssistantResponse\"\n rows=\"3\"\n placeholder=\"No assistant response is available yet.\"\n [value]=\"feedbackForm.assistantResponse\"\n readonly\n ></textarea>\n </label>\n\n <label class=\"support-ticket-field support-ticket-field-wide\">\n <span>What could be improved?</span>\n <textarea\n #feedbackInput\n pTextarea\n name=\"feedbackDetails\"\n rows=\"3\"\n placeholder=\"Tell us what you expected, what was missing, or how the response could be more useful.\"\n required\n [(ngModel)]=\"feedbackForm.feedback\"\n ></textarea>\n </label>\n </div>\n\n @if(!feedbackForm.name || !feedbackForm.email) {\n <p class=\"support-ticket-notice\" role=\"alert\">\n Your signed-in name and email are required. Please refresh your Nemesys session and try again.\n </p>\n }\n @if(feedbackError(); as error) {\n <p class=\"support-ticket-error\" role=\"alert\">{{ error }}</p>\n }\n </div>\n\n <footer class=\"support-ticket-actions feedback-actions\">\n <button\n pButton\n type=\"button\"\n label=\"Cancel\"\n severity=\"secondary\"\n outlined\n (click)=\"closeFeedback()\"\n ></button>\n <button\n pButton\n type=\"submit\"\n label=\"Send feedback\"\n icon=\"pi pi-send\"\n [loading]=\"feedbackSubmitting()\"\n [disabled]=\"!canSubmitFeedback()\"\n ></button>\n </footer>\n </form>\n }\n </div>\n </section>\n }\n</aside>\n", styles: [":host{position:relative;display:block;width:100%;height:100%;min-height:0}.assistant-launcher{position:relative;width:64px!important;height:64px!important;min-height:64px!important;padding:7px;border:1px solid rgba(124,58,237,.24)!important;border-radius:22px!important;color:inherit!important;background:radial-gradient(circle at 28% 16%,rgba(255,255,255,.98),transparent 38%),linear-gradient(145deg,#fff7ed,#f5f3ff 52%,#fdf2f8)!important;box-shadow:0 0 0 1px #ffffffd9 inset,0 12px 30px #5b21b62e!important;overflow:visible;transition:border-color .22s ease,box-shadow .22s ease,transform .22s cubic-bezier(.2,.8,.2,1);z-index:2}.assistant-launcher:before,.assistant-launcher:after{content:\"\";position:absolute;top:50%;left:50%;width:22px;height:2px;border-radius:999px;background:#0f6cae;opacity:0;transform:translate(-50%,-50%) scale(.6) rotate(0);transition:opacity .18s ease,transform .22s ease;z-index:1}.assistant-launcher:before{transform:translate(-50%,-50%) scale(.6) rotate(45deg)}.assistant-launcher:after{transform:translate(-50%,-50%) scale(.6) rotate(-45deg)}.assistant-launcher:hover,.assistant-launcher:focus-visible{border-color:#ec489975!important;background:radial-gradient(circle at 30% 18%,#fff,transparent 38%),linear-gradient(145deg,#ffedd5,#ede9fe,#fce7f3)!important;box-shadow:0 0 0 3px #a855f71a,0 16px 34px #6d28d938!important;transform:translateY(-2px)}.assistant-launcher.is-open{background:#fff!important;box-shadow:0 0 0 2px #0078c838,0 14px 32px #0f172a2e!important;transform:translateY(0)}.assistant-launcher.is-open:before,.assistant-launcher.is-open:after{opacity:1}.assistant-launcher.is-open:before{transform:translate(-50%,-50%) scale(1) rotate(45deg)}.assistant-launcher.is-open:after{transform:translate(-50%,-50%) scale(1) rotate(-45deg)}.mascot{position:relative;display:inline-grid;width:54px;height:54px;place-items:center;transform-origin:50% 72%;transition:opacity .18s ease,transform .24s ease,filter .24s ease;z-index:0}.mascot-aura{position:absolute;inset:5px;border-radius:50%;background:conic-gradient(from 25deg,#f472b66b,#fbbf2452,#2dd4bf57,#8b5cf66b,#f472b66b);filter:blur(7px);animation:mascot-aura 3s ease-in-out infinite}.mascot-art{position:relative;width:100%;height:100%;overflow:visible;filter:drop-shadow(0 5px 5px rgba(2,75,116,.2));animation:mascot-idle 3.4s ease-in-out infinite}.mascot-shell{fill:#7c3aed}.mascot-ear-left{fill:#ec4899}.mascot-ear-right{fill:#f97316}.mascot-ear{transform-box:fill-box;transform-origin:center}.mascot-face{fill:#211747;stroke:#ffffff4d;stroke-width:1}.mascot-signal{fill:#facc15;stroke:#fff;stroke-width:1.5;transform-box:fill-box;transform-origin:center;animation:mascot-signal 2.2s ease-out infinite}.mascot-antenna,.mascot-sparkle,.mascot-shell-shine,.mascot-smile,.mascot-mark{fill:none;stroke-linecap:round;stroke-linejoin:round}.mascot-antenna{stroke:#6d28d9;stroke-width:2.5}.mascot-sparkle{stroke:#ec4899;stroke-width:2;transform-box:fill-box;transform-origin:center;animation:mascot-sparkle 3.4s ease-in-out infinite}.mascot-shell-shine{stroke:#e9d5ffd1;stroke-width:2}.mascot-eye{fill:#5eead4;transform-box:fill-box;transform-origin:center;animation:mascot-blink 5.2s ease-in-out infinite}.mascot-smile{stroke:#fbbf24;stroke-width:2}.mascot-mark{stroke:#ffffffd1;stroke-width:2.2}.assistant-launcher:hover .mascot-art,.assistant-launcher:focus-visible .mascot-art{animation:mascot-greet .7s cubic-bezier(.2,.8,.2,1)}.assistant-launcher:hover .mascot-ear-right,.assistant-launcher:focus-visible .mascot-ear-right{animation:mascot-ear-wave .7s ease-in-out}.assistant-launcher.is-open .mascot{filter:saturate(1.08);opacity:.24;transform:scale(.82) rotate(-5deg)}.mascot.large{width:52px;height:52px;flex:0 0 auto}@keyframes mascot-idle{0%,to{transform:translateY(0) rotate(0)}50%{transform:translateY(-2px) rotate(1deg)}}@keyframes mascot-greet{0%,to{transform:translateY(0) rotate(0)}35%{transform:translateY(-4px) rotate(-5deg)}65%{transform:translateY(-2px) rotate(4deg)}}@keyframes mascot-ear-wave{0%,to{transform:rotate(0) scaleY(1)}50%{transform:rotate(-12deg) scaleY(1.12)}}@keyframes mascot-blink{0%,45%,49%,to{transform:scaleY(1)}47%{transform:scaleY(.12)}}@keyframes mascot-signal{0%,55%,to{opacity:1;transform:scale(1)}70%{opacity:.55;transform:scale(1.42)}}@keyframes mascot-sparkle{0%,62%,to{opacity:0;transform:scale(.5) rotate(0)}72%{opacity:1;transform:scale(1) rotate(90deg)}84%{opacity:0;transform:scale(.7) rotate(150deg)}}@keyframes mascot-aura{0%,to{opacity:.45;transform:scale(.88)}50%{opacity:.85;transform:scale(1.08)}}.assistant-window{position:relative;width:100%;height:100%;min-height:0;border:1px solid rgba(148,163,184,.24);border-radius:24px;background:#fffffff5;box-shadow:0 24px 70px #0f172a33,0 0 0 1px #ffffffad inset;overflow:hidden;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.assistant-panel{display:grid;grid-template-rows:auto 1fr auto;height:100%;min-height:0;border-radius:inherit;background:linear-gradient(180deg,#f8fafcd1,#f1f5f9f5),var(--max-canvas, #f8fafc);overflow:hidden}.assistant-header,.assistant-composer{display:flex;gap:12px;align-items:center;padding:16px 18px;background:#ffffffeb;border-bottom:1px solid rgba(226,232,240,.86)}.assistant-identity{display:grid;gap:5px;min-width:0}.assistant-name{margin:0;width:fit-content;color:var(--max-accent, #2563eb);font:inherit;font-weight:600}.assistant-subtitle{color:#64748b;font-size:10px;font-weight:600;letter-spacing:.1em;line-height:1.2;text-transform:uppercase}.sources span{color:#64748b;font-size:12px;font-weight:600}.assistant-header .header-action:first-of-type{margin-left:auto}.assistant-header .header-action{width:38px;height:38px;margin-left:0;color:#475569;background:transparent}.assistant-header .header-action:hover{background:#0f172a0f}.assistant-messages{min-height:0;overflow:auto;padding:18px;scrollbar-width:thin}.assistant-messages,.assistant-table-wrap,.assistant-rota-scroll{scrollbar-color:#cbd5e1 transparent;scrollbar-width:thin}.assistant-messages::-webkit-scrollbar,.assistant-table-wrap::-webkit-scrollbar,.assistant-rota-scroll::-webkit-scrollbar{width:6px;height:6px}.assistant-messages::-webkit-scrollbar-track,.assistant-table-wrap::-webkit-scrollbar-track,.assistant-rota-scroll::-webkit-scrollbar-track{background:transparent}.assistant-messages::-webkit-scrollbar-thumb,.assistant-table-wrap::-webkit-scrollbar-thumb,.assistant-rota-scroll::-webkit-scrollbar-thumb{border-radius:999px;background:#cbd5e1}.message{position:relative;width:fit-content;max-width:92%;margin-bottom:14px;padding:12px;border:1px solid var(--border-color, #e2e8f0);border-radius:16px;background:#fff;box-shadow:0 1px 2px #0f172a14,0 10px 24px #0f172a0f;-webkit-user-select:text;user-select:text}.message.assistant{width:100%;max-width:100%}.message.user{width:fit-content;max-width:88%;margin-left:auto;color:#fff;background:var(--primary-color, #2563eb);border-color:var(--border-color, #e2e8f0);border-bottom-right-radius:6px}.message.user p{color:inherit}.message.error{border-color:var(--danger-color, #dc2626)}.message.streaming{padding:0;border:0;color:var(--text-color-secondary, #64748b);background:transparent;box-shadow:none;font-style:italic}.streaming-progress{background:linear-gradient(100deg,var(--max-muted, #64748b) 20%,var(--primary-color, #2563eb) 42%,#a855f7 50%,var(--primary-color, #2563eb) 58%,var(--max-muted, #64748b) 80%);background-size:220% 100%;background-clip:text;-webkit-background-clip:text;-webkit-text-fill-color:transparent;white-space:pre-line;animation:assistant-progress-shimmer 2.2s ease-in-out infinite}@keyframes assistant-progress-shimmer{0%{background-position:120% 0}to{background-position:-20% 0}}.message p{margin:0;line-height:1.45}.assistant-result{color:#1e293b}.assistant-cards{display:grid;gap:10px;margin-top:12px}.assistant-card{overflow:hidden;border:1px solid #e2e8f0;border-radius:12px;background:#fff;box-shadow:0 3px 12px #0f172a0d;font-weight:400}.assistant-card>header{display:grid;gap:3px;padding:13px 16px;border-bottom:1px solid #e2e8f0}.assistant-card-title{color:#0f172a;font-size:14px;font-weight:600}.assistant-card-subtitle,.assistant-card>footer{color:#64748b;font-size:12px}.assistant-card-metrics{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));padding:16px}.assistant-card-metric{display:grid;min-width:0;align-content:start;gap:5px}.assistant-card-metric-wide{grid-column:1/-1}.assistant-card-label{color:#64748b;font-size:11px;font-weight:500;letter-spacing:.01em;line-height:1.25}.assistant-card-value{color:#0f172a;font-size:14px;font-weight:600;line-height:1.4;overflow-wrap:anywhere}.assistant-card-metric[data-tone=positive] .assistant-card-value{color:#047857}.assistant-card-metric[data-tone=warning] .assistant-card-value{color:#b45309}.assistant-card :is(strong,b){font-weight:600}.assistant-card>footer{padding:0 16px 14px}:host ::ng-deep .assistant-markdown{line-height:1.45}:host ::ng-deep .assistant-markdown>:first-child{margin-top:0}:host ::ng-deep .assistant-markdown>:last-child{margin-bottom:0}:host ::ng-deep .assistant-markdown p{margin:0 0 8px}:host ::ng-deep .assistant-markdown ul,:host ::ng-deep .assistant-markdown ol{margin:8px 0;padding-left:22px}:host ::ng-deep .assistant-markdown li+li{margin-top:4px}:host ::ng-deep .assistant-markdown strong{font-weight:700}:host ::ng-deep .assistant-markdown code{padding:1px 4px;border-radius:4px;background:#e2e8f0;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:.9em}:host ::ng-deep .assistant-markdown a{color:var(--primary-color, #2563eb);text-decoration:underline}.assistant-status{display:inline-flex;margin-top:8px;padding:3px 8px;border-radius:999px;color:#475569;background:#e2e8f0;font-size:11px;font-weight:600;text-transform:capitalize}.pending-action{display:grid;gap:9px;margin-top:12px;padding:12px;border:1px solid #f59e0b;border-radius:12px;background:#fffbeb}.pending-action-heading{display:flex;align-items:center;justify-content:space-between;color:#92400e}.pending-action-heading span{padding:2px 7px;border-radius:999px;color:#78350f;background:#fde68a;font-size:11px;font-weight:700}.pending-action small{color:#78716c}.pending-action-buttons{display:flex;gap:8px}.action-decision{color:#475569;font-weight:600}.assistant-sources{display:grid;gap:4px;margin-top:12px;padding-top:10px;border-top:1px solid #e2e8f0;color:#64748b;font-size:12px}.assistant-shift-groups,.assistant-shift-group{display:grid;gap:10px}.assistant-shift-groups,.assistant-rota{margin-top:12px}.assistant-shift-group h3,.assistant-rota h3{margin:0;color:#0f172a;font-size:13px;font-weight:600}.assistant-shift-card-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:9px}.assistant-rota{display:grid;gap:10px}.assistant-rota-heading{display:grid;gap:8px}.assistant-rota-summary{display:flex;flex-wrap:wrap;gap:7px}.assistant-rota-summary>span{display:grid;gap:2px;min-width:86px;padding:7px 9px;border:1px solid #e2e8f0;border-radius:8px;background:#f8fafc}.assistant-rota-summary small{color:#64748b;font-size:9px;font-weight:600;text-transform:uppercase}.assistant-rota-summary strong{color:#334155;font-size:11px}.assistant-rota-scroll{max-width:100%;overflow-x:auto;border:1px solid #e2e8f0;border-radius:10px;background:#fff}.assistant-rota-week{min-width:1288px}.assistant-rota-week+.assistant-rota-week{border-top:1px solid #cbd5e1}.assistant-rota-week-heading{display:flex;align-items:center;justify-content:space-between;padding:8px 10px;color:#334155;background:#f1f5f9}.assistant-rota-week-heading strong{font-size:12px}.assistant-rota-week-heading span{color:#64748b;font-size:10px}.assistant-rota-week-grid{display:grid;grid-template-columns:repeat(7,minmax(184px,1fr))}.assistant-rota-day{min-width:0;min-height:120px;border-right:1px solid #e2e8f0}.assistant-rota-day:last-child{border-right:0}.assistant-rota-day>header{display:flex;align-items:baseline;justify-content:space-between;padding:7px 8px;border-bottom:1px solid #e2e8f0;color:#334155;background:#f8fafc}.assistant-rota-day>header strong{font-size:10px}.assistant-rota-day>header span{color:#64748b;font-size:9px}.assistant-rota-day-shifts{display:grid;gap:7px;padding:7px}.assistant-rota-empty,.assistant-rota-no-weeks{margin:0;color:#94a3b8;font-size:10px;font-style:italic}.assistant-visualisations{display:grid;gap:10px;margin-top:12px}.assistant-visualisation{display:grid;gap:12px;padding:13px;border:1px solid #dbeafe;border-radius:14px;background:linear-gradient(145deg,#f8fbff,#fff)}.assistant-visualisation h3{margin:0;color:#0f172a;font-size:13px;font-weight:600}.assistant-export-heading{display:flex;min-width:0;gap:8px;align-items:center}.assistant-export-heading h3{min-width:0}.assistant-export-action{flex:0 0 auto;margin-left:auto;padding:0;color:inherit;background:transparent;border-color:transparent;box-shadow:none}:host ::ng-deep .assistant-export-action .p-button-icon{font-size:20px!important}.assistant-export-action-pdf{color:#d32f2f}.assistant-export-action-excel{color:#217346}.assistant-export-action-pdf:hover{color:#b71c1c;background:transparent;border-color:transparent}.assistant-export-action-excel:hover{color:#185c37;background:transparent;border-color:transparent}.assistant-doughnut-layout{display:grid;grid-template-columns:112px minmax(0,1fr);gap:14px;align-items:center}.assistant-doughnut{position:relative;display:grid;place-items:center;width:112px;aspect-ratio:1}.assistant-doughnut svg{width:100%;height:100%;transform:rotate(-90deg)}.assistant-doughnut circle{fill:none;stroke-width:6}.assistant-doughnut-track{stroke:#e2e8f0}.assistant-doughnut-segment{transition:stroke-dasharray .18s ease}.assistant-doughnut>span{position:absolute;display:grid;color:#64748b;font-size:9px;line-height:1.1;text-align:center}.assistant-doughnut>span strong{color:#0f172a;font-size:18px}.assistant-chart-legend{display:grid;gap:7px;min-width:0}.assistant-chart-legend-item{display:grid;grid-template-columns:9px minmax(0,1fr) auto;gap:7px;align-items:center;color:#475569;font-size:11px}.assistant-chart-legend-item i{width:9px;height:9px;border-radius:999px}.assistant-chart-legend-item strong,.assistant-bar-label strong{color:#0f172a;font-size:11px;font-weight:600}.assistant-bar-chart,.assistant-bar-row{display:grid;gap:6px}.assistant-bar-chart{gap:11px}.assistant-bar-label{display:flex;gap:12px;align-items:baseline;justify-content:space-between;color:#475569;font-size:11px}.assistant-bar-track{height:9px;overflow:hidden;border-radius:999px;background:#e2e8f0}.assistant-bar-track i{display:block;height:100%;min-width:0;border-radius:var(--max-frame-radius, 0);transition:width .18s ease}.assistant-tables{display:grid;gap:10px;margin-top:12px}.assistant-table-section{display:grid;gap:6px}.assistant-table-section h3{margin:0;color:#0f172a;font-size:13px;font-weight:600}.assistant-table-wrap{overflow:auto;max-height:450px;border:1px solid var(--border-color, #e2e8f0);border-radius:var(--border-radius, 6px)}.assistant-table-wrap table{width:100%;min-width:420px;border-collapse:collapse;background:#fff}.assistant-table-wrap th,.assistant-table-wrap td{padding:8px 10px;border-bottom:1px solid var(--border-color, #e2e8f0);color:#334155;font-size:12px;line-height:1.35;text-align:left;vertical-align:top}.assistant-table-wrap th{position:sticky;z-index:1;top:0;color:#475569;font-weight:600;background:#f8fafc}.assistant-table-wrap tr:last-child td{border-bottom:0}.assistant-table-actions{display:flex;flex-wrap:wrap;gap:6px;min-width:150px}.details-toggle{display:flex;width:fit-content;margin:10px 0 0 auto;padding:0;border:0;color:var(--primary-color, #2563eb);background:transparent;font:inherit;font-size:13px;font-weight:400;text-decoration:underline;text-underline-offset:3px;cursor:pointer}.details-toggle:hover{color:var(--primary-dark-color, #1d4ed8)}.details-toggle:focus-visible{outline:2px solid var(--primary-color, #2563eb);outline-offset:3px}.developer-details{display:grid;gap:12px;margin-top:12px;padding:12px;border:1px solid var(--border-color, #e2e8f0);border-radius:10px;background:#f8fafc}.developer-details-header h3,.developer-details-header p{margin:0}.developer-details-header h3{color:#0f172a;font-size:13px;font-weight:600}.developer-details-header p{margin-top:2px;color:#64748b;font-size:11px}.workflow-trace{display:grid;gap:0;margin:0;padding:0;list-style:none}.workflow-step{display:block;min-width:0}.workflow-category{color:#64748b;font-size:9px;font-weight:600;letter-spacing:.06em;text-transform:uppercase}.workflow-meta{display:grid;flex:0 0 auto;gap:2px;justify-items:end;color:#64748b;font-size:9px}.workflow-status{padding:2px 5px;border-radius:999px;color:#334155;background:#e2e8f0;font-weight:600;text-transform:capitalize}.workflow-step[data-status=succeeded] .workflow-status{color:#166534;background:#dcfce7}.workflow-step[data-status=failed] .workflow-status{color:#991b1b;background:#fee2e2}.trace-json{display:grid;gap:4px;margin-top:8px}.trace-json>span{color:#64748b;font-size:10px;font-weight:600;text-transform:uppercase}.trace-json pre{max-height:280px;margin:0;padding:8px;overflow:auto;border-radius:6px;color:#dbeafe;background:#0f172a;font-size:10px;line-height:1.45;white-space:pre-wrap;overflow-wrap:anywhere}.trace-error{display:grid;gap:3px;margin-top:8px;padding:8px;border-left:3px solid #dc2626;border-radius:4px;color:#991b1b;background:#fef2f2;font-size:11px}.developer-details-header{display:flex;gap:12px;align-items:flex-start;justify-content:space-between}.developer-eyebrow{color:var(--text-color, #0f172a);font-size:9px;font-weight:600;letter-spacing:.08em;text-transform:uppercase}.trace-section-label{color:var(--text-color, #0f172a);font-size:9px;font-weight:600;text-decoration:underline;text-underline-offset:3px}.trace-run-summary{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:7px}.trace-metric{display:grid;gap:3px;min-width:0;padding:9px;border:1px solid #e2e8f0;border-radius:8px;background:#fff}.trace-metric span,.trace-loop-policy span{color:#64748b;font-size:9px;font-weight:600}.trace-metric strong{color:#0f172a;font-size:13px}.trace-loop-policy{display:grid;grid-template-columns:minmax(0,1fr) auto;grid-column:1/-1;gap:5px 12px;align-items:center;padding:10px;border:1px solid #c7d2fe;border-radius:9px;background:#eef2ff}.trace-loop-policy div{display:grid;gap:2px}.trace-loop-policy strong{color:#312e81;font-size:11px}.trace-loop-policy p{grid-column:1/-1;margin:0;color:#475569;font-size:10px;line-height:1.45}.trace-no-loop{padding:3px 7px;border-radius:999px;color:#166534!important;background:#dcfce7;font-weight:600!important}.workflow-summary{margin:9px 0 0;color:#475569;font-size:10.5px;line-height:1.5}.trace-technology{display:grid;gap:6px;margin-top:10px;padding:8px;border:1px solid #dbeafe;border-radius:7px;background:#f8fbff}.trace-inline-facts{display:flex;flex-wrap:wrap;gap:5px}.trace-inline-facts>span{display:grid;gap:1px;max-width:100%;padding:4px 6px;border-radius:5px;color:#1e293b;background:#fff;font-size:9.5px;overflow-wrap:anywhere}.trace-inline-facts small{color:#64748b;font-size:8px;font-weight:600;text-transform:uppercase}.trace-control{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:4px 8px;margin-top:8px;padding:8px;border-left:3px solid #8b5cf6;border-radius:5px;background:#f5f3ff}.trace-control>div{display:grid;gap:2px}.trace-control strong,.trace-control>span{color:#5b21b6;font-size:9.5px}.trace-control p{grid-column:1/-1;margin:0;color:#475569;font-size:9.5px;line-height:1.4}.trace-query,.trace-section,.trace-arguments,.trace-ranking-wrap{display:grid;gap:5px;margin-top:10px}.trace-query>span,.trace-transform>div>span,.trace-vector>span,.trace-payload-grid section>span,.trace-tool-call>span,.trace-supabase-call span,.trace-decision>span{color:#64748b;font-size:9px;font-weight:600;text-transform:uppercase}.trace-query>span,.trace-vector>span,.trace-payload-grid section>span,.trace-tool-call>span,.trace-decision>span{color:var(--text-color, #0f172a);text-decoration:underline;text-underline-offset:3px}.trace-query blockquote{margin:0;padding:8px 10px;border-left:3px solid #2563eb;border-radius:5px;color:#172554;background:#eff6ff;font-size:11px;font-weight:600;line-height:1.45}.trace-query-compact blockquote{border-color:#8b5cf6;color:#4c1d95;background:#f5f3ff}.trace-card-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:7px;margin-top:9px}.trace-data-card{min-width:0;padding:8px;border:1px solid #e2e8f0;border-radius:7px;background:#f8fafc}.trace-data-card-accent{border-color:#bfdbfe;background:#eff6ff}.trace-data-card h5{margin:0 0 5px;color:var(--text-color, #0f172a);font-size:10px;font-weight:600;text-decoration:underline;text-underline-offset:3px}.trace-field-list,.trace-argument-grid{display:grid;gap:4px;margin:0}.trace-field-list>div{display:grid;grid-template-columns:minmax(70px,.7fr) minmax(0,1.3fr);gap:6px}.trace-field-list dt,.trace-argument-grid dt{color:#64748b;font-size:8.5px}.trace-field-list dd,.trace-argument-grid dd{margin:0;color:#1e293b;font-size:9px;font-weight:600;overflow-wrap:anywhere}.trace-transform{display:grid;grid-template-columns:minmax(0,1fr) 18px minmax(0,1fr);gap:6px;align-items:stretch;margin-top:10px}.trace-transform>div{display:grid;gap:5px;padding:9px;border:1px solid #e2e8f0;border-radius:7px;background:#f8fafc}.trace-transform .trace-transform-result{border-color:#bfdbfe;background:#eff6ff}.trace-transform p{margin:0;color:#1e293b;font-size:10px;font-weight:600;line-height:1.4}.trace-transform-arrow{display:grid;place-items:center;color:#2563eb;font-size:16px;font-weight:600}.trace-entity-list{display:flex;flex-wrap:wrap;gap:5px}.trace-entity-list>span{display:flex;gap:5px;align-items:center;padding:4px 7px;border:1px solid #fed7aa;border-radius:999px;color:#9a3412;background:#fff7ed;font-size:9.5px}.trace-entity-list small{color:#c2410c;font-size:7.5px;font-weight:600;text-transform:uppercase}.trace-stat-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px;margin-top:8px}.trace-stat-grid>div{display:grid;gap:2px;padding:7px;border:1px solid #e2e8f0;border-radius:6px}.trace-stat-grid span{color:#64748b;font-size:8.5px}.trace-stat-grid strong{color:#0f172a;font-size:10px;overflow-wrap:anywhere}.trace-vector{display:grid;gap:4px;margin-top:7px}.trace-vector code{padding:7px;overflow:auto;border-radius:5px;color:#c4b5fd;background:#1e1b4b;font-size:8.5px;white-space:nowrap}.trace-supabase-call{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px;margin-top:10px;padding:9px;border:1px solid #a7f3d0;border-radius:7px;background:#ecfdf5}.trace-supabase-call>div{display:grid;gap:2px}.trace-supabase-call strong{color:#065f46;font-size:10px;overflow-wrap:anywhere}.trace-table-list{grid-column:1/-1}.trace-table-list>div{display:flex;flex-wrap:wrap;gap:4px}.trace-table-list code{padding:3px 5px;border-radius:4px;color:#065f46;background:#d1fae5;font-size:8.5px}.trace-decision{display:grid;gap:4px;margin-top:7px;padding:9px;border-left:3px solid #16a34a;border-radius:5px;background:#f0fdf4}.trace-decision strong{color:#14532d;font-size:11px}.trace-decision div{display:flex;flex-wrap:wrap;gap:8px;color:#166534;font-size:8.5px}.trace-ranking-wrap{overflow:auto}.trace-ranking{width:100%;min-width:610px;border-collapse:collapse;font-size:8.5px}.trace-ranking th,.trace-ranking td{padding:6px;border-bottom:1px solid #e2e8f0;color:#475569;text-align:right;vertical-align:top}.trace-ranking th{color:#64748b;background:#f8fafc;font-size:8px;text-transform:uppercase}.trace-ranking th:nth-child(2),.trace-ranking td:nth-child(2){text-align:left}.trace-ranking td:nth-child(2){display:grid;gap:2px;min-width:145px}.trace-ranking strong{color:#1e293b;font-size:9px}.trace-ranking code{color:#64748b;font-size:7.5px}.trace-argument-grid{grid-template-columns:repeat(2,minmax(0,1fr));margin-top:3px}.trace-argument-grid>div{min-width:0;padding:7px;border:1px solid #e2e8f0;border-radius:6px;background:#f8fafc}.trace-tool-call,.trace-api-route{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin-top:8px;padding:8px;border-radius:6px;color:#dbeafe;background:#0f172a}.trace-tool-call>span{width:100%;color:#94a3b8}.trace-tool-call strong{color:#bfdbfe;font-size:10px}.trace-tool-call pre,.trace-payload-grid pre{width:100%;max-height:220px;margin:0;overflow:auto;color:#dbeafe;font-size:9px;line-height:1.45;white-space:pre-wrap;overflow-wrap:anywhere}.trace-api-route>code{flex:1 1 180px;color:#e2e8f0;font-size:9px;overflow-wrap:anywhere}.trace-http-method,.trace-http-status{padding:3px 6px;border-radius:4px;color:#fff;background:#2563eb;font-size:8.5px;font-weight:600}.trace-http-status.success{color:#bbf7d0;background:#166534}.trace-http-status.error{color:#fecaca;background:#991b1b}.trace-payload-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px;margin-top:7px}.trace-payload-grid section{display:grid;gap:5px;min-width:0;padding:8px;border:1px solid #334155;border-radius:6px;background:#0f172a}.trace-payload-grid section>span{color:#94a3b8}.trace-error.trace-warning{border-left-color:#f59e0b;color:#92400e;background:#fffbeb}.trace-error-legacy{display:none}.trace-error-heading{font-size:10px}.details-dialog-backdrop{position:fixed;inset:0;z-index:20;display:grid;padding:14px;place-items:center;background:#0f172a7a;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}.details-dialog-backdrop .developer-details{display:block;width:100%;max-height:100%;margin:0;padding:0 14px 14px;overflow:auto;overscroll-behavior:contain;border:0;border-radius:14px;background:#fff;box-shadow:0 24px 70px #0f172a4d}.details-dialog-backdrop .developer-details-header{position:sticky;top:0;z-index:3;margin:0 -14px 14px;padding:14px;border-bottom:1px solid #e2e8f0;background:#fffffff7;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}.details-dialog-actions{display:flex;flex:0 0 auto;gap:7px;align-items:center}.details-dialog-close{display:grid;width:30px;height:30px;padding:0;place-items:center;border:1px solid #e2e8f0;border-radius:8px;color:#475569;background:#fff;cursor:pointer}.details-dialog-close:hover{color:#0f172a;background:#f1f5f9}.details-dialog-close:focus-visible{outline:2px solid #2563eb;outline-offset:2px}.details-dialog-backdrop .trace-run-summary{margin-bottom:6px;padding-bottom:14px;border-bottom:1px solid #cbd5e1}.details-dialog-backdrop .trace-metric{padding:0 9px;border:0;border-right:1px solid #e2e8f0;border-radius:0;background:transparent}.details-dialog-backdrop .trace-metric:nth-child(4){border-right:0}.details-dialog-backdrop .trace-loop-policy{margin-top:5px;padding:9px 0 0;border:0;border-top:1px solid #e2e8f0;border-radius:0;background:transparent}.details-dialog-backdrop .workflow-trace{display:block}.details-dialog-backdrop .workflow-step{display:block;border-bottom:1px solid #cbd5e1}.workflow-section{display:block}.workflow-step-toggle{display:flex;gap:14px;align-items:center;justify-content:space-between;width:100%;padding:14px 2px;border:0;color:inherit;background:transparent;font:inherit;text-align:left;cursor:pointer}.workflow-step-toggle:hover{background:#f8fafc}.workflow-step-toggle:focus-visible{outline:2px solid #2563eb;outline-offset:-2px}.workflow-step-toggle>div:first-child{display:grid;min-width:0;gap:2px}.workflow-step-toggle h4{margin:0;color:var(--text-color, #0f172a);font-size:12px;font-weight:600;line-height:1.4;text-decoration:underline;text-decoration-color:#94a3b8;text-underline-offset:4px}.workflow-step-number{display:block;color:var(--primary-color, #2563eb);font-size:13px;font-weight:600}.workflow-expand-icon{color:#64748b;font-size:10px}.workflow-step-content{padding:0 2px 16px}.details-dialog-backdrop .workflow-summary{margin-top:0;padding-bottom:10px;border-bottom:1px solid #e2e8f0}.details-dialog-backdrop .trace-technology,.details-dialog-backdrop .trace-control{padding:9px 0;border:0;border-bottom:1px solid #e2e8f0;border-radius:0;background:transparent}.details-dialog-backdrop .trace-control{border-left:0}.details-dialog-backdrop .trace-inline-facts>span{padding:0 8px 0 0;border-right:1px solid #e2e8f0;border-radius:0;background:transparent}.details-dialog-backdrop :is(h3,h4,h5,strong,.workflow-status,.trace-section-label,.developer-eyebrow){font-weight:600!important}@media (max-width: 520px){.trace-run-summary,.trace-card-grid,.trace-stat-grid,.trace-payload-grid,.trace-argument-grid,.trace-transform{grid-template-columns:1fr}.trace-transform-arrow{transform:rotate(90deg)}}.suggestions{display:grid;gap:0;margin-top:12px}.entity-options{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin-top:12px}.suggestion-chip{justify-content:flex-start;width:100%;padding:6px 0;border:1px solid transparent;border-radius:999px;color:var(--primary-color, #2563eb);background:transparent;font-weight:600;box-shadow:none;text-align:left;transition:padding .16s ease,border-color .16s ease,background .16s ease,box-shadow .16s ease}.suggestion-chip:hover{padding:6px 12px;border-color:rgba(var(--primary-color-rgb, 37, 99, 235),.28);color:var(--primary-color, #2563eb);background:rgba(var(--primary-color-rgb, 37, 99, 235),.08);box-shadow:0 4px 14px #0f172a0f}.response-details{display:grid;gap:12px;margin-top:12px}.response-section{display:grid;gap:8px;padding-bottom:12px;border-bottom:1px solid var(--border-color, #e2e8f0)}.response-section:last-child{padding-bottom:0;border-bottom:0}.response-section h3{margin:0;color:#0f172a;font-size:13px;font-weight:600}.quoted{padding:8px 10px;border-left:5px solid var(--primary-color, #2563eb);border-radius:var(--border-radius, 6px);color:#1e293b;background:#f8fafc}.detail-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;margin:0}.detail-grid div{min-width:0;padding:8px;border-radius:var(--border-radius, 6px);background:#f8fafc}.detail-grid dt{margin-bottom:3px;color:#64748b;font-size:11px;font-weight:600;text-transform:uppercase}.detail-grid dd{margin:0;color:#334155;font-size:13px;font-weight:600;line-height:1.35;overflow-wrap:anywhere}.detail-grid dd span{display:block;margin-top:2px;color:#64748b;font-size:11px}.api-call-summary,.json-block{display:grid;gap:6px;padding:8px;border-radius:var(--border-radius, 6px);background:#f8fafc}.api-call-summary .detail-label,.json-block .detail-label{color:#64748b;font-size:11px;font-weight:600;text-transform:uppercase}.api-call-summary code{color:var(--secondary-color, #0f172a);font-weight:600;white-space:normal;word-break:break-word}.json-block pre{max-height:220px;margin:0;overflow:auto;color:#0f172a;font-size:12px;line-height:1.45;white-space:pre-wrap;overflow-wrap:anywhere}.assistant-composer{padding:14px 16px 16px;border-top:1px solid rgba(226,232,240,.9);border-bottom:0;box-shadow:0 -10px 30px #0f172a0a}.assistant-composer textarea{flex:1;min-height:46px;max-height:120px;border-radius:18px;background:#fff;resize:vertical}.assistant-composer button[type=submit]{width:44px;height:44px;border-radius:16px}@keyframes pulse{to{opacity:.35;transform:translateY(-2px)}}@media (prefers-reduced-motion: reduce){.mascot-aura,.mascot-art,.mascot-eye,.mascot-signal,.mascot-sparkle,.assistant-launcher:hover .mascot-art,.assistant-launcher:focus-visible .mascot-art,.assistant-launcher:hover .mascot-ear-right,.assistant-launcher:focus-visible .mascot-ear-right{animation:none}.assistant-launcher,.mascot{transition-duration:.01ms}}@media (max-width: 640px){.assistant-messages{padding:14px}.detail-grid,.entity-options,.assistant-card-metrics{grid-template-columns:1fr}.assistant-card-metric{padding:0}}\n", ":host{--max-accent: var(--max-assistant-accent, #1a73e8);--max-accent-strong: var(--max-assistant-accent-strong, #1557b0);--max-canvas: var(--max-assistant-canvas, #f8f9fa);--max-surface: var(--max-assistant-surface, #ffffff);--max-surface-soft: color-mix(in srgb, var(--max-accent) 6%, var(--max-surface));--max-text: var(--max-assistant-text, #1f1f1f);--max-muted: var(--max-assistant-muted, #5f6368);--max-border: var(--max-assistant-border, #dfe1e5);--max-success: var(--max-assistant-success, #188038);--max-warning: var(--max-assistant-warning, #b06000);--max-danger: var(--max-assistant-danger, #b3261e);--max-support-text: var(--max-assistant-support-text, #3c4043);--max-control-radius: var(--max-assistant-control-radius, 6px);--max-frame-radius: var(--max-assistant-frame-radius, 0px);--max-sparkles-gradient: linear-gradient( 135deg, color-mix(in srgb, var(--max-accent) 58%, white) 0%, var(--max-accent) 46%, color-mix(in srgb, var(--max-accent) 55%, var(--max-accent-strong)) 72%, var(--max-accent-strong) 100% );--max-header-action-size: 40px;--max-header-content-size: 20px;--primary-color: var(--max-accent);--primary-color-rgb: var(--max-assistant-accent-rgb, 26, 115, 232);--primary-dark-color: var(--max-accent-strong);--background: var(--max-canvas);--background-color: var(--max-canvas);--panel-background: var(--max-surface);--text-color: var(--max-text);--text-color-secondary: var(--max-muted);--border-color: var(--max-border);--success-color: var(--max-success);--warning-color: var(--max-warning);--error-color: var(--max-danger);--danger-color: var(--max-danger);--border-radius: var(--max-control-radius);position:relative;display:block;width:100%;height:100%;min-height:0;isolation:isolate;color:var(--max-text);font-family:Arial,Helvetica,sans-serif;font-size:16px;font-weight:400;line-height:normal;text-align:left;color-scheme:light}:host,:host *{box-sizing:border-box}:host button,:host ::ng-deep .p-button-label{text-transform:capitalize}.max-assistant-sparkles{display:inline-flex;flex:0 0 auto;align-items:center;justify-content:center;font-size:var(--max-header-content-size);line-height:1;vertical-align:middle;color:transparent;background:var(--assistant-sparkles-gradient, var(--max-sparkles-gradient));background-clip:text;-webkit-background-clip:text;-webkit-text-fill-color:transparent;filter:drop-shadow(0 2px 3px rgba(60,64,67,.18))}.assistant-window{position:relative;inset:auto;width:100%;height:100%;max-height:none;overflow:hidden;opacity:1;visibility:visible;pointer-events:auto;translate:none;transform:none;border:0;border-radius:var(--max-frame-radius);background:var(--max-canvas);box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none;transition:none}.assistant-panel{grid-template-rows:72px minmax(0,1fr) auto;color:var(--max-text);background:radial-gradient(circle at 48% 0%,color-mix(in srgb,var(--max-accent) 10%,transparent),transparent 46%),radial-gradient(circle at 92% 72%,color-mix(in srgb,#c58af9 8%,transparent),transparent 38%),linear-gradient(145deg,var(--max-canvas),color-mix(in srgb,var(--max-canvas) 94%,#edf3ff))}.assistant-header{display:flex;gap:20px;align-items:center;padding:0 24px;border:0;border-bottom:1px solid var(--max-border);background:color-mix(in srgb,var(--max-canvas) 88%,transparent);-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px)}.assistant-header-actions{display:flex;gap:4px;align-items:center;margin-left:auto}.assistant-identity{display:flex;flex-direction:column}.assistant-name{align-self:flex-start;margin:0;color:transparent;background:var(--assistant-sparkles-gradient, var(--max-sparkles-gradient));background-clip:text;-webkit-background-clip:text;-webkit-text-fill-color:transparent;font:inherit;font-size:var(--max-header-content-size);font-weight:600;line-height:1}.assistant-subtitle{color:var(--max-muted);font-size:12px;font-weight:400;letter-spacing:0;line-height:1;text-transform:none}.assistant-name-row{display:flex;align-items:center;gap:8px}.assistant-beta-tag{padding:3px 6px;color:var(--max-text-color, #475569);font-size:11px;font-weight:700;line-height:1;background:var(--max-accent-color, #e2e8f0);border-radius:4px}.assistant-header .header-action{display:inline-flex;width:var(--max-header-action-size);min-width:var(--max-header-action-size);height:var(--max-header-action-size);align-items:center;justify-content:center;margin:0;padding:0;appearance:none;border:0;border-radius:50%;color:var(--max-muted);background:transparent;font:inherit;line-height:1;cursor:pointer}.assistant-header .header-action-icon{font-size:var(--max-header-content-size);font-weight:400;line-height:1}.assistant-header .header-action:hover{color:var(--max-text);background:var(--max-surface-soft)}.assistant-header .header-action:focus-visible{outline:2px solid var(--max-accent);outline-offset:2px}.assistant-messages{width:min(820px,100%);min-height:0;justify-self:center;box-sizing:border-box;padding:44px 28px 32px;overflow-x:hidden;overflow-y:auto;scrollbar-color:color-mix(in srgb,var(--max-muted) 25%,transparent) transparent;scrollbar-width:thin}.assistant-table-wrap,.assistant-rota-scroll{scrollbar-color:color-mix(in srgb,var(--max-muted) 25%,transparent) transparent;scrollbar-width:thin}.assistant-messages::-webkit-scrollbar-thumb,.assistant-table-wrap::-webkit-scrollbar-thumb,.assistant-rota-scroll::-webkit-scrollbar-thumb{background:color-mix(in srgb,var(--max-muted) 25%,transparent)}.message{width:100%;max-width:100%;box-sizing:border-box;margin:0 0 34px;padding:0;border:0;border-radius:0;color:var(--max-text);background:transparent;box-shadow:none}.message.assistant{width:100%;max-width:100%}.message.user{width:fit-content;max-width:min(76%,640px);margin:0 0 32px auto;padding:13px 18px;border:1px solid var(--max-border);border-radius:18px 18px 6px;color:var(--max-text);background:linear-gradient(135deg,color-mix(in srgb,var(--max-accent) 10%,var(--max-surface)),color-mix(in srgb,var(--max-accent) 5%,var(--max-surface)));box-shadow:0 1px 2px color-mix(in srgb,var(--max-text) 7%,transparent),0 6px 18px color-mix(in srgb,var(--max-accent) 8%,transparent)}.message.user p{color:inherit;font-size:15px;line-height:1.55}.message.error{padding-left:16px;border-left:3px solid var(--max-danger)}.message.streaming{display:flex;gap:10px;align-items:center;padding:0;color:var(--max-muted);background:transparent;font-style:normal}.message.streaming:before{width:16px;height:16px;flex:0 0 auto;border-radius:6px;background:var(--assistant-sparkles-gradient, var(--max-sparkles-gradient));content:\"\";animation:max-thinking 1.4s ease-in-out infinite alternate}.streaming-progress{color:var(--max-muted);font-size:14px;white-space:pre-line}.message p,.assistant-result,:host ::ng-deep .assistant-markdown{color:var(--max-text);font-size:15px;line-height:1.65}:host ::ng-deep .assistant-markdown code{color:var(--max-text);background:color-mix(in srgb,var(--max-muted) 10%,transparent)}.message.welcome{min-height:260px;margin:0;padding-top:clamp(28px,8vh,90px);text-align:center}.message.welcome .assistant-markdown{max-width:650px;margin:0 auto}:host ::ng-deep .message.welcome .assistant-markdown p{margin:0;font-size:clamp(28px,3.2vw,42px);font-weight:500;letter-spacing:-.04em;line-height:1.18}:host ::ng-deep .message.welcome-message .assistant-markdown p{color:var(--max-accent)}.welcome-description{max-width:620px;margin:0 auto!important;margin-top:2rem!important;color:var(--max-text);font-size:16px;line-height:1.6;white-space:pre-line}.support-welcome-card{display:flex;width:min(460px,100%);min-height:70px;gap:13px;align-items:center;margin:22px auto 0;padding:13px 16px;appearance:none;border:1px solid color-mix(in srgb,var(--max-accent) 24%,var(--max-border));border-radius:16px;color:var(--max-support-text);background:linear-gradient(135deg,color-mix(in srgb,var(--max-accent) 10%,var(--max-surface)),var(--max-surface) 58%);box-shadow:0 8px 28px #3c40431a;font:inherit;text-align:left;cursor:pointer;transition:border-color .16s ease,box-shadow .16s ease,transform .16s ease}.support-welcome-card:hover{border-color:color-mix(in srgb,var(--max-accent) 48%,var(--max-border));box-shadow:0 12px 32px #3c404324;transform:translateY(-1px)}.support-welcome-card:focus-visible,.support-ticket-shortcut:focus-visible,.support-ticket-close:focus-visible,.response-feedback-action:focus-visible{outline:2px solid var(--max-accent);outline-offset:2px}.support-welcome-icon,.support-ticket-header-icon,.support-ticket-success-icon{display:inline-flex;width:40px;height:40px;flex:0 0 40px;align-items:center;justify-content:center;border-radius:13px;color:var(--max-accent);background:color-mix(in srgb,var(--max-accent) 13%,var(--max-surface));font-size:18px}.support-welcome-copy{display:flex;min-width:0;flex:1;flex-direction:column;gap:5px}.support-welcome-copy strong{color:var(--max-support-text);font-size:15px;font-weight:600;line-height:1.25}.support-welcome-copy small{color:var(--max-muted);font-size:12px;line-height:1.45}.support-welcome-arrow{flex:0 0 auto;color:var(--max-accent);font-size:16px}@media (min-width: 641px) and (max-height: 850px){.message.welcome{min-height:0;padding-top:22px;padding-bottom:22px}:host ::ng-deep .message.welcome .assistant-markdown p{font-size:clamp(24px,3vw,34px)}.welcome-description{margin-top:1rem!important;font-size:14px;line-height:1.45}.support-welcome-card{min-height:58px;margin-top:14px;padding:10px 13px}}.assistant-cards{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin-top:20px}.assistant-card{overflow:hidden;border:1px solid var(--max-border);border-radius:18px;background:var(--max-surface);box-shadow:none}.assistant-card>header{gap:4px;padding:16px;border-bottom:1px solid var(--max-border)}.assistant-card>header strong{color:var(--max-text);font-size:15px;font-weight:600}.assistant-card>header span,.assistant-card>footer,.assistant-card-metric span{color:var(--max-muted)}.assistant-card-metric{padding:14px;border-color:var(--max-border)}.assistant-card-metric strong{color:var(--max-text);font-size:10px}.assistant-card-metric[data-tone=positive] strong{color:var(--max-success)}.assistant-card-metric[data-tone=warning] strong{color:var(--max-warning)}.assistant-card>footer{padding:10px 16px;border-color:var(--max-border);background:var(--max-surface-soft)}.assistant-search-result>header{display:flex;gap:12px;align-items:center}.assistant-search-result-icon{display:inline-flex;width:36px;height:36px;flex:0 0 36px;align-items:center;justify-content:center;border-radius:12px;color:var(--max-accent);background:var(--max-surface-soft);font-size:16px;font-weight:400;line-height:1}.assistant-search-result-copy{display:grid;min-width:0;gap:4px}.assistant-search-result .suggestions{display:grid;grid-template-columns:repeat(auto-fit,minmax(132px,1fr));gap:10px;margin:0;padding:16px}.assistant-search-result .suggestion-chip{width:100%;min-height:44px;align-items:center;justify-content:flex-start;padding:10px 14px;border-color:var(--max-border);background:var(--max-surface-soft);line-height:1.25}.assistant-search-result .suggestion-chip:hover{padding:10px 14px;background:color-mix(in srgb,var(--max-accent) 10%,var(--max-surface))}:host ::ng-deep .assistant-search-result .suggestion-chip .p-button-icon{font-weight:400;line-height:1}.assistant-status{margin-top:12px;padding:0;border-radius:0;color:var(--max-muted);background:transparent;font-size:11px;letter-spacing:.05em;text-transform:uppercase}.pending-action{gap:12px;margin-top:18px;padding:18px;border:1px solid color-mix(in srgb,var(--max-warning) 38%,var(--max-border));border-radius:18px;background:color-mix(in srgb,var(--max-warning) 6%,var(--max-surface))}.pending-action-heading{color:var(--max-text)}.pending-action-heading span{color:var(--max-warning);background:transparent}.pending-action small,.action-decision{color:var(--max-muted)}.assistant-sources{margin-top:20px;padding-top:14px;border-color:var(--max-border);color:var(--max-muted)}.assistant-shift-groups,.assistant-rota{margin-top:20px}.assistant-shift-group h3,.assistant-rota h3,.assistant-rota-summary strong,.assistant-rota-week-heading,.assistant-rota-day>header{color:var(--max-text)}.assistant-rota-summary>span,.assistant-rota-scroll{border-color:var(--max-border);background:var(--max-surface)}.assistant-rota-summary small,.assistant-rota-week-heading span,.assistant-rota-day>header span{color:var(--max-muted)}.assistant-rota-week-heading,.assistant-rota-day>header{background:var(--max-surface-soft)}.assistant-rota-week+.assistant-rota-week,.assistant-rota-day,.assistant-rota-day>header{border-color:var(--max-border)}.assistant-visualisations{grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin-top:20px}.assistant-visualisation{padding:16px;border-color:var(--max-border);border-radius:18px;background:var(--max-surface)}.assistant-visualisation h3,.assistant-doughnut>span strong,.assistant-chart-legend-item strong,.assistant-bar-label strong{color:var(--max-text)}.assistant-chart-legend-item,.assistant-bar-label,.assistant-doughnut>span{color:var(--max-muted)}.assistant-doughnut-track,.assistant-bar-track{stroke:var(--max-border);background:var(--max-border)}.sources span{color:var(--max-muted)}.assistant-tables{gap:18px;margin-top:20px}.assistant-table-section{gap:10px}.assistant-table-section h3{color:var(--max-text);font-size:14px}.assistant-table-wrap{border-color:var(--max-border);border-radius:16px}.assistant-table-wrap table{background:var(--max-surface)}.assistant-table-wrap th,.assistant-table-wrap td{padding:11px 13px;border-color:var(--max-border);color:var(--max-text);font-size:12px}.assistant-table-wrap th{color:var(--max-muted);background:var(--max-surface-soft)}.details-toggle{margin:0 0 0 auto;color:var(--max-accent);font-size:12px;text-decoration:underline;text-underline-offset:3px}.details-toggle:hover{color:var(--max-accent-strong);text-decoration:underline}.suggestions{display:flex;flex-wrap:wrap;gap:8px;margin-top:18px}.capability-options{display:grid;gap:22px;margin-top:18px}.clarification-options{margin-top:18px}.capability-option-section{display:grid;gap:10px}.capability-option-section h3{margin:0;color:var(--max-text);font-size:14px;font-weight:600}.capability-option-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}.capability-option-card{display:grid;grid-template-columns:auto minmax(0,1fr) auto;gap:10px;width:100%;min-height:76px;padding:12px 14px;align-items:center;border:1px solid var(--max-border);border-radius:var(--border-radius, 6px);color:var(--max-text);background:var(--max-surface);box-shadow:none;text-align:left}.capability-option-card:hover:not(:disabled){border-color:color-mix(in srgb,var(--max-accent) 32%,var(--max-border));color:var(--max-text);background:var(--max-surface-soft);box-shadow:none}.capability-option-number{display:inline-flex;min-width:24px;height:24px;align-items:center;justify-content:center;border-radius:50%;color:var(--max-accent-strong);background:var(--max-surface-soft);font-size:12px;font-weight:600}.capability-option-copy{line-height:1.4}.capability-option-arrow{color:var(--max-muted);font-size:13px}.response-actions{display:flex;align-items:center;margin-top:8px}.response-feedback-action{display:inline-flex;width:32px;height:32px;align-items:center;justify-content:center;padding:0;appearance:none;border:0;border-radius:50%;color:var(--max-muted);background:transparent;font:inherit;cursor:pointer}.response-feedback-action:hover{color:var(--max-accent);background:var(--max-surface-soft)}.suggestion-chip{justify-content:flex-start;width:auto;min-height:40px;padding:8px 14px;border:1px solid var(--max-border);border-radius:14px;color:var(--max-text);background:var(--max-surface);font-weight:400;box-shadow:none;text-align:left}.suggestion-chip:hover{padding:8px 14px;border-color:color-mix(in srgb,var(--max-accent) 28%,var(--max-border));color:var(--max-text);background:var(--max-surface-soft);box-shadow:none}.message.welcome .suggestions{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin-top:0}.message.welcome .suggestion-chip{width:100%;min-height:74px;padding:14px 16px;align-items:flex-start;border-radius:18px;line-height:1.35}.message.welcome .suggestion-chip:hover{padding:14px 16px;transform:translateY(-1px)}.assistant-footer{display:flex;width:min(780px,100% - 48px);flex-direction:column;align-items:flex-end;justify-self:center}.support-ticket-shortcut{display:inline-flex;min-height:34px;gap:7px;align-items:center;margin:0 10px 9px 0;padding:7px 12px;appearance:none;border:1px solid color-mix(in srgb,var(--max-accent) 24%,var(--max-border));border-radius:999px;color:var(--max-accent-strong);background:color-mix(in srgb,var(--max-accent) 7%,var(--max-surface));box-shadow:0 2px 8px #3c404314;font:inherit;font-size:13px;font-weight:600;line-height:1;cursor:pointer}.support-ticket-shortcut:hover{border-color:color-mix(in srgb,var(--max-accent) 45%,var(--max-border));background:color-mix(in srgb,var(--max-accent) 11%,var(--max-surface))}.support-ticket-shortcut i{font-size:15px}.assistant-composer{display:flex;width:100%;box-sizing:border-box;gap:8px;align-items:center;margin:0 0 24px;padding:8px 8px 8px 18px;border:1px solid var(--max-border);border-radius:28px;background:var(--max-surface);box-shadow:0 1px 2px #3c404314,0 6px 20px #3c40431a;transition:border-color .16s ease,box-shadow .16s ease}.assistant-composer:focus-within{border-color:color-mix(in srgb,var(--max-accent) 36%,var(--max-border));box-shadow:0 1px 2px #3c404314,0 8px 24px #3c404324}.assistant-composer textarea{flex:1;min-height:44px;height:44px;max-height:132px;box-sizing:border-box;padding:11px 2px;border:0;border-radius:0;outline:0;color:var(--max-text);background:transparent;box-shadow:none;font:inherit;font-size:15px;line-height:22px;resize:none}.assistant-composer textarea::placeholder{color:var(--max-muted);opacity:.84}.assistant-composer textarea:focus{border:0;outline:0;box-shadow:none}.assistant-composer button[type=submit]{width:44px;height:44px;flex:0 0 auto;border-radius:50%;background:var(--max-accent)}.assistant-composer button[type=submit]:disabled{border-color:transparent;color:var(--max-muted);background:transparent;opacity:.5}.support-ticket-overlay{position:absolute;z-index:100;inset:0;display:flex;overflow:auto;align-items:flex-start;justify-content:center;padding:24px;background:#1f1f1f70;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.support-ticket-dialog{position:relative;display:flex;width:min(700px,100%);flex-direction:column;margin:auto 0;border:1px solid var(--max-border);border-radius:22px;color:var(--max-support-text);background:var(--max-surface);box-shadow:0 24px 72px #1f1f1f47}.feedback-dialog{max-height:calc(100% - 48px);overflow:hidden}.feedback-dialog .feedback-form{display:flex;min-height:0;flex:1 1 auto;flex-direction:column;overflow:hidden;padding:0}.feedback-header{position:sticky;z-index:2;top:0;flex:0 0 auto;background:var(--max-surface)}.feedback-header p{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.feedback-form-body{min-height:0;flex:1 1 auto;padding:18px 22px;overflow-y:auto;overscroll-behavior:contain}.feedback-form .support-ticket-fields{gap:12px 18px}.feedback-form .support-ticket-field{gap:5px}.feedback-form .support-ticket-field textarea{min-height:72px}.feedback-actions{position:sticky;z-index:2;bottom:0;flex:0 0 auto;margin:0;padding:14px 22px;border-top:1px solid var(--max-border);background:var(--max-surface)}.support-ticket-header{display:flex;gap:14px;align-items:center;padding:20px 22px;border-bottom:1px solid var(--max-border)}.support-ticket-header-icon{width:44px;height:44px;flex-basis:44px;border-radius:14px;font-size:19px}.support-ticket-header>div{min-width:0;flex:1}.support-ticket-header h2,.support-ticket-header p,.support-ticket-success h3,.support-ticket-success p{margin:0}.support-ticket-header h2{color:var(--max-support-text);font-size:19px;font-weight:600;line-height:1.3}.support-ticket-header p{margin-top:3px;color:var(--max-muted);font-size:13px;line-height:1.4}.support-ticket-close{display:inline-flex;width:38px;height:38px;flex:0 0 38px;align-items:center;justify-content:center;padding:0;appearance:none;border:0;border-radius:50%;color:var(--max-muted);background:transparent;font:inherit;cursor:pointer}.support-ticket-close:hover{color:var(--max-support-text);background:var(--max-surface-soft)}.support-ticket-form{min-height:0;overflow:visible;padding:22px}.support-ticket-fields{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:18px}.support-ticket-field{display:flex;min-width:0;flex-direction:column;gap:7px;color:var(--max-support-text);font-size:13px;font-weight:600}.support-ticket-field>span{display:flex;gap:5px;align-items:baseline}.support-ticket-field>span small{color:var(--max-muted);font-size:11px;font-weight:400}.support-ticket-field-wide{grid-column:1/-1}.support-ticket-field input,.support-ticket-field textarea{width:100%;min-height:44px;padding:10px 12px;border:1px solid var(--max-border);border-radius:10px;outline:0;color:var(--max-support-text);background:var(--max-surface);box-shadow:none;font:inherit;font-size:14px;font-weight:400;line-height:1.45}.support-ticket-field textarea{min-height:116px;resize:vertical}.support-ticket-field input[readonly],.support-ticket-field textarea[readonly]{color:color-mix(in srgb,var(--max-support-text) 82%,var(--max-muted));background:color-mix(in srgb,var(--max-muted) 6%,var(--max-surface));cursor:default}.support-ticket-field input::placeholder,.support-ticket-field textarea::placeholder{color:var(--max-muted);opacity:.82}.support-ticket-field input:focus,.support-ticket-field textarea:focus{border-color:var(--max-accent);box-shadow:0 0 0 3px color-mix(in srgb,var(--max-accent) 13%,transparent)}:host ::ng-deep .support-ticket-dialog .p-select,:host ::ng-deep .support-ticket-dialog .p-multiselect{min-height:44px;border-color:var(--max-border);border-radius:10px;color:var(--max-support-text);background:var(--max-surface);box-shadow:none;font:inherit;font-size:14px;font-weight:400}:host ::ng-deep .support-ticket-dialog .p-select:not(.p-disabled).p-focus,:host ::ng-deep .support-ticket-dialog .p-multiselect:not(.p-disabled).p-focus{border-color:var(--max-accent);box-shadow:0 0 0 3px color-mix(in srgb,var(--max-accent) 13%,transparent)}:host ::ng-deep .support-ticket-dialog .p-select-label,:host ::ng-deep .support-ticket-dialog .p-multiselect-label,:host ::ng-deep .support-ticket-dialog .p-select-dropdown,:host ::ng-deep .support-ticket-dialog .p-multiselect-dropdown{color:var(--max-support-text);font:inherit;font-size:14px}:host ::ng-deep .support-ticket-dialog .p-select-label,:host ::ng-deep .support-ticket-dialog .p-multiselect-label{display:flex;min-height:42px;align-items:center}:host ::ng-deep .support-ticket-dialog .p-multiselect-label{flex-wrap:wrap;gap:5px;padding-block:5px}:host ::ng-deep .support-selected-tags{display:inline-flex;min-width:0;flex-wrap:wrap;gap:5px;align-items:center}:host ::ng-deep .support-ticket-dialog .p-tag{font-size:12px;font-weight:600}:host ::ng-deep .support-ticket-dialog .p-tag-icon{font-size:11px}:host ::ng-deep .support-ticket-dialog .p-select-option,:host ::ng-deep .support-ticket-dialog .p-multiselect-option{color:var(--max-support-text)}:host ::ng-deep .support-ticket-dialog .p-select-overlay,:host ::ng-deep .support-ticket-dialog .p-multiselect-overlay{border-color:var(--max-border);border-radius:12px;color:var(--max-support-text);background:var(--max-surface);box-shadow:0 12px 32px #1f1f1f2e;font:inherit}.support-ticket-notice,.support-ticket-error{margin:16px 0 0;padding:10px 12px;border-radius:10px;font-size:13px;line-height:1.45}.support-ticket-notice{color:var(--max-warning);background:color-mix(in srgb,var(--max-warning) 9%,var(--max-surface))}.support-ticket-error{color:var(--max-danger);background:color-mix(in srgb,var(--max-danger) 8%,var(--max-surface))}.support-ticket-actions{display:flex;gap:10px;justify-content:flex-end;margin-top:22px}.support-ticket-success{display:flex;min-height:340px;align-items:center;justify-content:center;padding:38px 24px;flex-direction:column;text-align:center}.support-ticket-success-icon{width:64px;height:64px;flex-basis:64px;border-radius:50%;color:var(--max-success);background:color-mix(in srgb,var(--max-success) 12%,var(--max-surface));font-size:32px}.support-ticket-close i{font-size:20px}.support-ticket-success h3{margin-top:18px;color:var(--max-support-text);font-size:21px}.support-ticket-success p{max-width:420px;margin-top:7px;color:var(--max-muted);font-size:14px;line-height:1.5}.support-ticket-reference{display:flex;gap:6px;align-items:center;margin:22px 0;padding:10px 14px;border:1px solid var(--max-border);border-radius:10px;background:var(--max-surface-soft);font-size:13px}.support-ticket-reference span{color:var(--max-muted)}@keyframes max-thinking{0%{opacity:.55;transform:rotate(-8deg) scale(.86)}to{opacity:1;transform:rotate(8deg) scale(1)}}@media (prefers-reduced-motion: reduce){.message.streaming:before{animation:none}.suggestion-chip,.capability-option-card,.support-welcome-card{transition:none}}@media (max-width: 900px){.assistant-messages{padding-top:34px}}@media (max-width: 640px){.assistant-panel{grid-template-rows:64px minmax(0,1fr) auto}.assistant-header{padding:0 14px}.assistant-subtitle{display:none}.assistant-messages{padding:26px 18px 20px}.message.welcome{padding-top:24px}.message.welcome .suggestions,.assistant-cards,.assistant-visualisations,.capability-option-grid{grid-template-columns:1fr}.message.welcome .suggestion-chip{min-height:60px}.message.user{max-width:88%}.assistant-composer{width:100%;margin-bottom:12px}.assistant-footer{width:calc(100% - 24px)}.support-ticket-overlay{align-items:start;padding:10px}.support-ticket-dialog{max-height:none;border-radius:16px}.feedback-dialog{max-height:calc(100% - 20px)}.support-ticket-header{padding:16px}.support-ticket-header p{display:none}.feedback-header p{display:block}.feedback-form-body{padding:14px 16px}.feedback-actions{padding:12px 16px}.support-ticket-form{overflow:visible;padding:16px}.support-ticket-fields{grid-template-columns:1fr;gap:14px}.support-ticket-field-wide{grid-column:auto}.support-ticket-actions{flex-direction:column-reverse}.support-ticket-actions button{width:100%}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i5.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i5.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i5.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i5.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i6.ButtonDirective, selector: "[pButton]", inputs: ["ptButtonDirective", "hostName", "text", "plain", "raised", "size", "outlined", "rounded", "iconPos", "loadingIcon", "fluid", "label", "icon", "loading", "buttonProps", "severity"] }, { kind: "ngmodule", type: MultiSelectModule }, { kind: "component", type: i7.MultiSelect, selector: "p-multiSelect, p-multiselect, p-multi-select", inputs: ["id", "ariaLabel", "styleClass", "panelStyle", "panelStyleClass", "inputId", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "dataKey", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "chipIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "loading", "virtualScrollItemSize", "loadingIcon", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "showClear", "autofocus", "placeholder", "options", "filterValue", "selectAll", "focusOnHover", "filterFields", "selectOnFocus", "autoOptionFocus", "highlightOnSelect", "size", "variant", "fluid", "appendTo"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad", "onRemove", "onSelectAllChange"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i8.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i9.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "ngmodule", type: TextareaModule }, { kind: "directive", type: i10.Textarea, selector: "[pTextarea], [pInputTextarea]", inputs: ["autoResize", "pSize", "variant", "fluid", "invalid"], outputs: ["onResize"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i11.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip"] }, { kind: "component", type: MaxAgentEntityOptionComponent, selector: "max-agent-entity-option", inputs: ["entity", "disabled"], outputs: ["selected"] }, { kind: "component", type: MaxAgentShiftCardComponent, selector: "max-agent-shift-card", inputs: ["shift", "variant"] }, { kind: "pipe", type: i12.DatePipe, name: "date" }, { kind: "pipe", type: MaxAssistantMarkdownPipe, name: "maxAssistantMarkdown" }] });
|
|
1879
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.14", type: MaxAssistantComponent, isStandalone: true, selector: "max-assistant", inputs: { app: "app", assistantApiUrl: "assistantApiUrl", user: "user", context: "context", requestHeaders: "requestHeaders", developerDetailsEnabled: "developerDetailsEnabled" }, outputs: { hostAction: "hostAction", closeRequested: "closeRequested" }, host: { listeners: { "document:keydown.escape": "onDocumentEscape()" } }, viewQueries: [{ propertyName: "messagesViewport", first: true, predicate: ["messagesViewport"], descendants: true }, { propertyName: "composerInput", first: true, predicate: ["composerInput"], descendants: true }, { propertyName: "supportQueryInput", first: true, predicate: ["supportQueryInput"], descendants: true }, { propertyName: "feedbackInput", first: true, predicate: ["feedbackInput"], descendants: true }], ngImport: i0, template: "<aside\n class=\"assistant-window\"\n [attr.aria-label]=\"uiCopy.title\"\n role=\"region\"\n>\n <section class=\"assistant-panel\">\n <header class=\"assistant-header\">\n <i class=\"max-assistant-sparkles far fa-sparkles\" aria-hidden=\"true\"></i>\n <div class=\"assistant-identity\">\n <div class=\"assistant-name-row\">\n <h2 class=\"assistant-name\">{{ uiCopy.title }}</h2>\n <span class=\"assistant-beta-tag\">Beta</span>\n </div>\n <span class=\"assistant-subtitle\">{{ uiCopy.subtitle }}</span>\n </div>\n <div class=\"assistant-header-actions\">\n <button\n type=\"button\"\n class=\"header-action\"\n [attr.aria-label]=\"uiCopy.clearLabel\"\n [pTooltip]=\"uiCopy.clearTooltip\"\n tooltipPosition=\"bottom\"\n (click)=\"clearChatSession()\"\n >\n <i class=\"header-action-icon pi pi-refresh\" aria-hidden=\"true\"></i>\n </button>\n <button\n type=\"button\"\n class=\"header-action\"\n [attr.aria-label]=\"uiCopy.closeLabel\"\n [pTooltip]=\"uiCopy.closeTooltip\"\n tooltipPosition=\"bottom\"\n (click)=\"requestClose()\"\n >\n <i class=\"header-action-icon pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </header>\n\n <div #messagesViewport class=\"assistant-messages\">\n @for(message of messages(); track message.id) {\n <article\n class=\"message {{ message.role }}\"\n [class.welcome-message]=\"isWelcomeMessage(message)\"\n [class.welcome]=\"isWelcomeState(message)\"\n [class.error]=\"message.isError\"\n [class.streaming]=\"message.isStreaming\"\n [attr.aria-live]=\"message.isStreaming ? 'polite' : null\"\n [attr.aria-busy]=\"message.isStreaming || null\"\n [attr.role]=\"message.isStreaming ? 'status' : null\"\n >\n @if(message.isStreaming) {\n <p class=\"streaming-progress\">{{ message.content }}</p>\n } @else if(message.displayResponse; as responseDetails) {\n @if(responseDetails.markdown || responseDetails.agentInferredResponse || message.content) {\n <div\n class=\"assistant-result assistant-markdown\"\n [innerHTML]=\"(responseDetails.markdown || responseDetails.agentInferredResponse || message.content) | maxAssistantMarkdown\"\n ></div>\n }\n @if(message.cards?.length) {\n <div class=\"assistant-cards\">\n @for(card of message.cards ?? []; track $index) {\n <section class=\"assistant-card\">\n <header>\n <span class=\"assistant-card-title\">{{ card.title }}</span>\n @if(card.subtitle) {\n <span class=\"assistant-card-subtitle\">{{ card.subtitle }}</span>\n }\n </header>\n <div class=\"assistant-card-metrics\">\n @for(metric of card.metrics; track metric.label) {\n <div class=\"assistant-card-metric\" [class.assistant-card-metric-wide]=\"isListMetric(metric)\" [attr.data-tone]=\"metric.tone || 'default'\">\n <span class=\"assistant-card-label\">{{ metric.label }}</span>\n <span class=\"assistant-card-value\">{{ metric.value }}</span>\n </div>\n }\n </div>\n @if(card.footer) {\n <footer>{{ card.footer }}</footer>\n }\n </section>\n }\n </div>\n }\n @if(responseDetails.searchResults?.length) {\n <div class=\"assistant-cards assistant-search-results\" aria-label=\"Search results\">\n @for(result of responseDetails.searchResults ?? []; track $index) {\n <section class=\"assistant-card assistant-search-result\">\n <header>\n <i\n class=\"assistant-search-result-icon\"\n [class]=\"searchResultIcon(result.type)\"\n aria-hidden=\"true\"\n ></i>\n <div class=\"assistant-search-result-copy\">\n <strong>{{ result.title }}</strong>\n <span>{{ result.type }}</span>\n </div>\n </header>\n <div class=\"suggestions\" aria-label=\"Available destinations\">\n @for(action of result.actions; track action.label) {\n <button\n pButton\n type=\"button\"\n size=\"small\"\n severity=\"secondary\"\n class=\"suggestion-chip\"\n [label]=\"action.label\"\n [icon]=\"searchActionIcon(action)\"\n [disabled]=\"isSending()\"\n (click)=\"performHostAction(action.hostAction)\"\n ></button>\n }\n </div>\n </section>\n }\n </div>\n }\n @if(message.pendingAction; as pendingAction) {\n <section class=\"pending-action\" aria-label=\"Cortex action confirmation\">\n <div class=\"pending-action-heading\">\n <strong>Confirmation required</strong>\n <span>{{ pendingAction.method }}</span>\n </div>\n <p>{{ pendingAction.summary }}</p>\n <small>Expires {{ pendingAction.expiresAt | date: 'mediumTime' }}</small>\n @if(message.actionDecision; as actionDecision) {\n <p class=\"action-decision\">\n {{ actionDecision === 'approve' ? 'Approval sent' : 'Rejection sent' }}\n </p>\n } @else {\n <div class=\"pending-action-buttons\">\n <button\n pButton\n type=\"button\"\n size=\"small\"\n severity=\"success\"\n label=\"Approve\"\n [disabled]=\"isSending()\"\n (click)=\"resolvePendingAction(message, 'approve')\"\n ></button>\n <button\n pButton\n type=\"button\"\n size=\"small\"\n outlined\n severity=\"secondary\"\n label=\"Reject\"\n [disabled]=\"isSending()\"\n (click)=\"resolvePendingAction(message, 'reject')\"\n ></button>\n </div>\n }\n </section>\n }\n @if(responseDetails.shiftCardGroups?.length) {\n <div class=\"assistant-shift-groups\" aria-label=\"Team shifts\">\n @for(group of responseDetails.shiftCardGroups ?? []; track group.title) {\n <section class=\"assistant-shift-group\">\n <h3>{{ group.title }}</h3>\n <div class=\"assistant-shift-card-grid\">\n @for(shift of group.shifts; track shift.id || $index) {\n <max-agent-shift-card\n [shift]=\"shift\"\n variant=\"definition\"\n ></max-agent-shift-card>\n }\n </div>\n </section>\n }\n </div>\n }\n @if(responseDetails.rota; as rota) {\n <section class=\"assistant-rota\" [attr.aria-label]=\"rota.title\">\n <div class=\"assistant-rota-heading\">\n <h3>{{ rota.title }}</h3>\n <div class=\"assistant-rota-summary\">\n @if(rota.startDate) {\n <span><small>From</small><strong>{{ rota.startDate }}</strong></span>\n }\n <span><small>Weeks</small><strong>{{ rota.weeksCount }}</strong></span>\n @if(rota.contracted) {\n <span><small>Contracted</small><strong>{{ rota.contracted }}</strong></span>\n }\n @if(rota.autoPublish) {\n <span><small>Auto publish</small><strong>{{ rota.autoPublish }}</strong></span>\n }\n </div>\n </div>\n <div class=\"assistant-rota-scroll\">\n @for(week of rota.weeks; track week.week) {\n <section class=\"assistant-rota-week\">\n <header class=\"assistant-rota-week-heading\">\n <strong>Week {{ week.week }}</strong>\n @if(week.duration) {\n <span>{{ week.duration }}</span>\n }\n </header>\n <div class=\"assistant-rota-week-grid\">\n @for(day of week.days; track day.day) {\n <article class=\"assistant-rota-day\">\n <header>\n <strong>{{ day.label }}</strong>\n @if(day.period) {\n <span>{{ day.period }}</span>\n }\n </header>\n <div class=\"assistant-rota-day-shifts\">\n @for(shift of day.shifts; track shift.id || $index) {\n <max-agent-shift-card\n [shift]=\"shift\"\n variant=\"rota\"\n ></max-agent-shift-card>\n } @empty {\n <span class=\"assistant-rota-empty\">No shifts</span>\n }\n </div>\n </article>\n }\n </div>\n </section>\n } @empty {\n <p class=\"assistant-rota-no-weeks\">No rota weeks were returned.</p>\n }\n </div>\n </section>\n }\n @if(responseDetails.visualisations?.length) {\n <div class=\"assistant-visualisations\">\n @for(visualisation of responseDetails.visualisations ?? []; track visualisation.title) {\n <section class=\"assistant-visualisation\">\n <header class=\"assistant-export-heading\">\n <h3>{{ visualisation.title }}</h3>\n <button\n pButton\n type=\"button\"\n size=\"small\"\n severity=\"secondary\"\n class=\"assistant-export-action assistant-export-action-pdf\"\n icon=\"pi pi-file-pdf\"\n [attr.aria-label]=\"'Export ' + visualisation.title + ' as PDF'\"\n (click)=\"exportVisualisation(visualisation)\"\n ></button>\n </header>\n @if(visualisation.type === 'doughnut') {\n <div class=\"assistant-doughnut-layout\">\n <div\n class=\"assistant-doughnut\"\n role=\"img\"\n [attr.aria-label]=\"chartAriaLabel(visualisation)\"\n >\n <svg viewBox=\"0 0 42 42\" aria-hidden=\"true\" focusable=\"false\">\n <circle\n class=\"assistant-doughnut-track\"\n cx=\"21\"\n cy=\"21\"\n r=\"15.9155\"\n ></circle>\n @for(value of visualisation.values; track $index; let valueIndex = $index) {\n <circle\n class=\"assistant-doughnut-segment\"\n cx=\"21\"\n cy=\"21\"\n r=\"15.9155\"\n pathLength=\"100\"\n [attr.stroke]=\"chartColor(visualisation, valueIndex)\"\n [attr.stroke-dasharray]=\"doughnutDashArray(visualisation, valueIndex)\"\n [attr.stroke-dashoffset]=\"doughnutDashOffset(visualisation, valueIndex)\"\n ></circle>\n }\n </svg>\n <span><strong>{{ chartTotal(visualisation) }}</strong>{{ visualisation.valueLabel || 'people' }}</span>\n </div>\n <div class=\"assistant-chart-legend\">\n @for(label of visualisation.labels; track $index; let labelIndex = $index) {\n <div class=\"assistant-chart-legend-item\">\n <i [style.background]=\"chartColor(visualisation, labelIndex)\"></i>\n <span>{{ label }}</span>\n <strong>{{ visualisation.values[labelIndex] || 0 }}</strong>\n </div>\n }\n </div>\n </div>\n } @else {\n <div\n class=\"assistant-bar-chart\"\n role=\"img\"\n [attr.aria-label]=\"chartAriaLabel(visualisation)\"\n >\n @for(label of visualisation.labels; track $index; let labelIndex = $index) {\n <div class=\"assistant-bar-row\">\n <div class=\"assistant-bar-label\">\n <span>{{ label }}</span>\n <strong>{{ visualisation.values[labelIndex] || 0 }}</strong>\n </div>\n <div class=\"assistant-bar-track\" aria-hidden=\"true\">\n <i\n [style.width.%]=\"barWidth(visualisation, labelIndex)\"\n [style.background]=\"chartColor(visualisation, labelIndex)\"\n ></i>\n </div>\n </div>\n }\n </div>\n }\n </section>\n }\n </div>\n }\n @if(getResponseGrid(responseDetails).length) {\n <div class=\"assistant-tables\">\n @for(table of getResponseGrid(responseDetails); track $index; let tableIndex = $index) {\n <section class=\"assistant-table-section\">\n <header class=\"assistant-export-heading\">\n @if(table.title) {\n <h3>{{ table.title }}</h3>\n }\n <button\n pButton\n type=\"button\"\n size=\"small\"\n severity=\"secondary\"\n class=\"assistant-export-action assistant-export-action-excel\"\n icon=\"pi pi-file-excel\"\n [attr.aria-label]=\"'Export ' + (table.title || 'results') + ' to Excel'\"\n (click)=\"exportTable(table)\"\n ></button>\n </header>\n <div class=\"assistant-table-wrap\">\n <table>\n <thead>\n <tr>\n @if(table.pagination) {\n <th>SL. No</th>\n }\n @for(column of table.columns; track column.field) {\n <th>{{ column.header }}</th>\n }\n @if(table.actions?.length) {\n <th>Actions</th>\n }\n </tr>\n </thead>\n <tbody>\n @for(row of table.rows; track $index; let rowIndex = $index) {\n <tr>\n @if(table.pagination) {\n <td>{{ rowIndex + 1 }}</td>\n }\n @for(column of table.columns; track column.field) {\n <td>{{ row[column.field] }}</td>\n }\n @if(table.actions?.length) {\n <td>\n <div class=\"assistant-table-actions\">\n @for(action of getTableRowActions(table, rowIndex); track action.label) {\n <button\n pButton\n type=\"button\"\n size=\"small\"\n [severity]=\"action.tone || 'secondary'\"\n [outlined]=\"action.tone === 'danger'\"\n [label]=\"action.label\"\n [disabled]=\"isSending()\"\n (click)=\"useTableAction(action)\"\n ></button>\n }\n </div>\n </td>\n }\n </tr>\n }\n </tbody>\n </table>\n </div>\n @if(table.pagination; as pagination) {\n <footer class=\"assistant-table-pagination\">\n <span>{{ tablePageStatus(table) }}</span>\n @if(hasNextTablePage(table)) {\n <button\n pButton\n type=\"button\"\n size=\"small\"\n severity=\"secondary\"\n class=\"assistant-table-page-action\"\n icon=\"pi pi-arrow-down\"\n [label]=\"nextTablePageLabel(pagination)\"\n [loading]=\"isTablePageLoading(message.id, tableIndex)\"\n [disabled]=\"isSending()\"\n (click)=\"retrieveNextTablePage(message, table, tableIndex)\"\n ></button>\n }\n </footer>\n @if(tablePageError(message.id, tableIndex); as pageError) {\n <p class=\"assistant-table-page-error\" role=\"alert\">{{ pageError }}</p>\n }\n }\n </section>\n }\n </div>\n }\n @if(message.sources?.length) {\n <div class=\"assistant-sources\">\n <strong>Sources</strong>\n @for(source of message.sources ?? []; track source.citation) {\n <span>{{ source.citation }}</span>\n }\n </div>\n }\n @if(developerDetailsEnabled && message.developerTrace?.steps?.length) {\n @if(isDetailsVisible(message.id)) {\n <div class=\"details-dialog-backdrop\" (click)=\"toggleDetails(message.id)\">\n <section\n class=\"developer-details\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"Agent processing details\"\n (click)=\"$event.stopPropagation()\"\n >\n <header class=\"developer-details-header\">\n <div>\n <span class=\"developer-eyebrow\">Developer trace</span>\n <h3>How this request was processed</h3>\n <p>A technical, step-by-step account of routing, inference, tools and results.</p>\n </div>\n <div class=\"details-dialog-actions\">\n <button\n type=\"button\"\n class=\"details-dialog-close\"\n aria-label=\"Close processing details\"\n (click)=\"toggleDetails(message.id)\"\n >\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </header>\n\n @if(message.developerTrace!.run; as run) {\n <section class=\"trace-run-summary\" aria-label=\"Run summary\">\n <div class=\"trace-metric\"><span>Total runtime</span><strong>{{ run.durationMs }} ms</strong></div>\n <div class=\"trace-metric\"><span>Model calls</span><strong>{{ run.llmCalls }}</strong></div>\n <div class=\"trace-metric\"><span>Embedding calls</span><strong>{{ run.embeddingCalls }}</strong></div>\n <div class=\"trace-metric\"><span>API calls</span><strong>{{ run.apiCalls }}</strong></div>\n <div class=\"trace-loop-policy\">\n <div>\n <span>Execution architecture</span>\n <strong>Deterministic step pipeline</strong>\n </div>\n <span class=\"trace-no-loop\">No autonomous model loop</span>\n <p>{{ run.loopPolicy }}</p>\n </div>\n </section>\n }\n\n <ol class=\"workflow-trace\">\n @for(step of message.developerTrace!.steps; track step.id; let stepIndex = $index) {\n <li class=\"workflow-step\" [attr.data-status]=\"traceStepTone(step)\">\n <section class=\"workflow-section\">\n <button\n type=\"button\"\n class=\"workflow-step-toggle\"\n [attr.aria-expanded]=\"isTraceStepExpanded(message.id, step.id)\"\n (click)=\"toggleTraceStep(message.id, step.id)\"\n >\n <div>\n <span class=\"workflow-step-number\">Step {{ stepIndex + 1 }}</span>\n <h4>{{ step.title }}</h4>\n <span class=\"workflow-category\">{{ formatTraceCategory(step.category) }}</span>\n </div>\n <div class=\"workflow-meta\">\n <span class=\"workflow-status\">{{ traceStepStatus(step) }}</span>\n @if(step.durationMs !== undefined) {\n <span>{{ step.durationMs }} ms</span>\n }\n <i\n class=\"pi workflow-expand-icon\"\n [class.pi-chevron-down]=\"isTraceStepExpanded(message.id, step.id)\"\n [class.pi-chevron-right]=\"!isTraceStepExpanded(message.id, step.id)\"\n aria-hidden=\"true\"\n ></i>\n </div>\n </button>\n\n @if(isTraceStepExpanded(message.id, step.id)) {\n <div class=\"workflow-step-content\">\n @if(step.metadata?.summary) {\n <p class=\"workflow-summary\">{{ step.metadata!.summary }}</p>\n }\n\n @if(step.metadata?.technology; as technology) {\n <div class=\"trace-technology\">\n <span class=\"trace-section-label\">Technology</span>\n <div class=\"trace-inline-facts\">\n <span><small>Component</small>{{ technology.component }}</span>\n @if(technology.model) { <span><small>Model</small>{{ technology.model }}</span> }\n @if(technology.library) { <span><small>Library</small>{{ technology.library }}</span> }\n @if(technology.provider) { <span><small>Provider</small>{{ technology.provider }}</span> }\n @if(technology.operation) { <span><small>Operation</small>{{ technology.operation }}</span> }\n </div>\n </div>\n }\n\n @if(step.metadata?.control; as control) {\n <div class=\"trace-control\">\n <div>\n <span class=\"trace-section-label\">Stop control</span>\n <strong>{{ formatTraceLabel(control.mode) }}</strong>\n </div>\n @if(control.maximumIterations !== undefined) {\n <span>{{ control.iterationsUsed ?? 0 }} / {{ control.maximumIterations }} iteration</span>\n }\n <p>{{ control.stopCondition }}</p>\n </div>\n }\n\n @switch(step.category) {\n @case('request') {\n @if(traceField(step.input, 'userQuery'); as userQuery) {\n <div class=\"trace-query\">\n <span>Original user query</span>\n <blockquote>{{ formatTraceScalar(userQuery) }}</blockquote>\n </div>\n }\n <div class=\"trace-card-grid\">\n @for(group of [\n { label: 'Product', value: traceMapField(step.input, 'product') },\n { label: 'User', value: traceMapField(step.input, 'user') },\n { label: 'Request context', value: traceMapField(step.input, 'requestContext') },\n { label: 'Conversation', value: traceMapField(step.input, 'conversation') },\n { label: 'Live API context', value: traceMapField(step.input, 'liveApi') }\n ]; track group.label) {\n @if(group.value) {\n <section class=\"trace-data-card\">\n <h5>{{ group.label }}</h5>\n <dl class=\"trace-field-list\">\n @for(entry of traceEntries(group.value, group.label === 'User' ? ['permissions'] : []); track entry.key) {\n <div><dt>{{ entry.label }}</dt><dd>{{ formatTraceScalar(entry.value) }}</dd></div>\n }\n </dl>\n </section>\n }\n }\n </div>\n }\n\n @case('intent_projection') {\n <div class=\"trace-transform\">\n <div>\n <span>Original query</span>\n <p>{{ formatTraceScalar(traceField(step.output, 'originalUserQuery') ?? traceField(step.input, 'originalUserQuery')) }}</p>\n </div>\n <span class=\"trace-transform-arrow\" aria-hidden=\"true\">\u2192</span>\n <div class=\"trace-transform-result\">\n <span>Generalised intent sent to embedding</span>\n <p>{{ formatTraceScalar(traceField(step.output, 'generalisedIntent') ?? traceField(step.output, 'routingText')) }}</p>\n </div>\n </div>\n @if(traceArrayField(step.output, 'removedArguments').length) {\n <div class=\"trace-section\">\n <span class=\"trace-section-label\">Arguments removed before routing</span>\n <div class=\"trace-entity-list\">\n @for(argument of traceArrayField(step.output, 'removedArguments'); track $index) {\n <span><small>{{ formatTraceScalar(traceField(argument, 'kind')) }}</small>{{ formatTraceScalar(traceField(argument, 'value')) }}</span>\n }\n </div>\n </div>\n }\n }\n\n @case('embedding') {\n <div class=\"trace-query trace-query-compact\">\n <span>Embedded text</span>\n <blockquote>{{ formatTraceScalar(traceField(step.input, 'generalisedIntent')) }}</blockquote>\n </div>\n <div class=\"trace-stat-grid\">\n <div><span>Embedding model</span><strong>{{ formatTraceScalar(traceField(step.output, 'model') ?? traceField(step.input, 'model')) }}</strong></div>\n <div><span>Dimensions</span><strong>{{ formatTraceScalar(traceField(step.output, 'dimensions')) }}</strong></div>\n <div><span>Vector magnitude</span><strong>{{ formatTraceScalar(traceField(step.output, 'vectorMagnitude')) }}</strong></div>\n <div><span>Full vector exposed</span><strong>{{ formatTraceScalar(traceField(step.output, 'fullVectorShown')) }}</strong></div>\n </div>\n @if(traceField(step.output, 'vectorPreview'); as vectorPreview) {\n <div class=\"trace-vector\">\n <span>Vector preview</span>\n <code>{{ formatTraceScalar(vectorPreview) }}</code>\n </div>\n }\n }\n\n @case('capability_routing') {\n @if(traceMapField(step.output, 'routing'); as routing) {\n <div class=\"trace-supabase-call\">\n <div><span>Routing strategy</span><strong>{{ formatTraceScalar(traceField(routing, 'strategy')) }}</strong></div>\n <div><span>Cache status</span><strong>{{ formatTraceScalar(traceField(routing, 'cacheStatus')) }}</strong></div>\n <div><span>Supabase RPC executed</span><strong>{{ formatTraceScalar(traceField(routing, 'supabaseRpcExecuted')) }}</strong></div>\n <div><span>Vector search executed</span><strong>{{ formatTraceScalar(traceField(routing, 'vectorSearchExecuted')) }}</strong></div>\n @if(traceField(routing, 'supabaseRpcExecuted')) {\n <div><span>Supabase RPC</span><strong>{{ formatTraceScalar(traceField(routing, 'rpc')) }}</strong></div>\n <div><span>Database</span><strong>{{ formatTraceScalar(traceField(routing, 'database')) }}</strong></div>\n @if(traceArrayField(routing, 'tables').length) {\n <div class=\"trace-table-list\">\n <span>Tables searched</span>\n <div>\n @for(table of traceArrayField(routing, 'tables'); track $index) {\n <code>{{ formatTraceScalar(table) }}</code>\n }\n </div>\n </div>\n }\n }\n </div>\n } @else {\n <div class=\"trace-supabase-call\">\n <div><span>Supabase RPC</span><strong>{{ formatTraceScalar(traceField(step.input, 'rpc')) }}</strong></div>\n <div><span>Database</span><strong>{{ formatTraceScalar(traceField(step.input, 'database')) }}</strong></div>\n @if(traceArrayField(step.input, 'tables').length) {\n <div class=\"trace-table-list\">\n <span>Tables searched</span>\n <div>\n @for(table of traceArrayField(step.input, 'tables'); track $index) {\n <code>{{ formatTraceScalar(table) }}</code>\n }\n </div>\n </div>\n }\n </div>\n }\n @if(traceMapField(step.output, 'decision'); as decision) {\n <section class=\"trace-decision\">\n <span>Routing decision</span>\n <strong>{{ formatTraceScalar(decision['selectedCapabilityLabel'] ?? decision['selectedCapabilityKey']) }}</strong>\n <div>\n <span>Status: {{ formatTraceScalar(decision['status']) }}</span>\n <span>Confidence: {{ formatSimilarity(decision['confidence']) }}</span>\n <span>Runner-up: {{ formatSimilarity(decision['runnerUpConfidence']) }}</span>\n </div>\n </section>\n }\n @if(traceArrayField(step.output, 'matchedCapabilities').length) {\n <div class=\"trace-ranking-wrap\">\n <span class=\"trace-section-label\">Ranked capability matches</span>\n <table class=\"trace-ranking\">\n <thead><tr><th>#</th><th>Capability</th><th>Combined</th><th>Semantic</th><th>Definition</th><th>Example</th><th>Keyword</th></tr></thead>\n <tbody>\n @for(candidate of traceArrayField(step.output, 'matchedCapabilities'); track $index) {\n <tr>\n <td>{{ formatTraceScalar(traceField(candidate, 'rank')) }}</td>\n <td><strong>{{ formatTraceScalar(traceField(candidate, 'label')) }}</strong><code>{{ formatTraceScalar(traceField(candidate, 'capabilityKey')) }}</code></td>\n <td>{{ formatSimilarity(traceField(candidate, 'combinedScore')) }}</td>\n <td>{{ formatSimilarity(traceField(candidate, 'semanticScore')) }}</td>\n <td>{{ formatSimilarity(traceField(candidate, 'definitionScore')) }}</td>\n <td>{{ formatSimilarity(traceField(candidate, 'exampleScore')) }}</td>\n <td>{{ formatSimilarity(traceField(candidate, 'keywordScore')) }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n }\n\n @case('argument_extraction') {\n <div class=\"trace-card-grid\">\n @if(traceMapField(step.output, 'selectedCapability') ?? traceMapField(step.input, 'selectedCapability'); as capability) {\n <section class=\"trace-data-card trace-data-card-accent\">\n <h5>Selected capability</h5>\n <dl class=\"trace-field-list\">\n @for(entry of traceEntries(capability); track entry.key) {\n <div><dt>{{ entry.label }}</dt><dd>{{ formatTraceScalar(entry.value) }}</dd></div>\n }\n </dl>\n </section>\n }\n @if(traceMapField(step.input, 'tool'); as tool) {\n <section class=\"trace-data-card\">\n <h5>Allowlisted tool</h5>\n <dl class=\"trace-field-list\">\n @for(entry of traceEntries(tool); track entry.key) {\n <div><dt>{{ entry.label }}</dt><dd>{{ formatTraceScalar(entry.value) }}</dd></div>\n }\n </dl>\n </section>\n }\n </div>\n @if(traceMapField(step.output, 'extractedArguments'); as arguments) {\n <section class=\"trace-arguments\">\n <span class=\"trace-section-label\">Arguments extracted from the original query</span>\n <dl class=\"trace-argument-grid\">\n @for(entry of traceEntries(arguments); track entry.key) {\n <div><dt>{{ entry.label }}</dt><dd>{{ formatTraceScalar(entry.value) }}</dd></div>\n }\n </dl>\n </section>\n }\n @if(traceMapField(step.output, 'plannedToolCall'); as plannedCall) {\n <div class=\"trace-tool-call\">\n <span>Planned tool call</span>\n <strong>{{ formatTraceScalar(plannedCall['method']) }} \u00B7 {{ formatTraceScalar(plannedCall['toolName']) }}</strong>\n <pre>{{ formatTraceValue(plannedCall['arguments']) }}</pre>\n </div>\n }\n }\n\n @case('api_call') {\n @if(traceField(step.input, 'sql'); as sql) {\n <div class=\"trace-tool-call trace-sql-query\">\n <span>SQL sent to MySQL MCP</span>\n <strong>{{ formatTraceScalar(traceField(step.input, 'toolName')) }}</strong>\n <pre>{{ formatTraceScalar(sql) }}</pre>\n </div>\n }\n @if(traceField(step.input, 'method') || traceField(step.input, 'path')) {\n <div class=\"trace-api-route\">\n <span class=\"trace-http-method\">{{ formatTraceScalar(traceField(step.input, 'method')) }}</span>\n <code>{{ formatTraceScalar(traceField(step.input, 'path')) }}</code>\n @if(getHttpStatus(step); as statusCode) {\n <span class=\"trace-http-status\" [class.success]=\"isHttpSuccessful(step)\" [class.error]=\"!isHttpSuccessful(step)\">\n HTTP {{ statusCode }} \u00B7 {{ isHttpSuccessful(step) ? 'Success' : 'Error' }}\n </span>\n }\n </div>\n }\n <div class=\"trace-payload-grid\">\n @if(traceField(step.input, 'body'); as requestBody) {\n <section><span>Request payload</span><pre>{{ formatTraceValue(requestBody) }}</pre></section>\n }\n @if(traceField(step.output, 'response'); as apiResponse) {\n <section><span>API response</span><pre>{{ formatTraceValue(apiResponse) }}</pre></section>\n }\n @if(traceField(step.input, 'sql') && step.output !== undefined) {\n <section><span>MySQL MCP execution details</span><pre>{{ formatTraceValue(step.output) }}</pre></section>\n }\n </div>\n }\n\n @case('action') {\n <div class=\"trace-card-grid\">\n <section class=\"trace-data-card\">\n <h5>Workflow input</h5>\n <dl class=\"trace-field-list\">\n @for(entry of traceEntries(step.input); track entry.key) {\n <div><dt>{{ entry.label }}</dt><dd>{{ formatTraceScalar(entry.value) }}</dd></div>\n }\n </dl>\n </section>\n <section class=\"trace-data-card trace-data-card-accent\">\n <h5>Outcome</h5>\n <dl class=\"trace-field-list\">\n @for(entry of traceEntries(step.output); track entry.key) {\n <div><dt>{{ entry.label }}</dt><dd>{{ formatTraceScalar(entry.value) }}</dd></div>\n }\n </dl>\n </section>\n </div>\n }\n\n @case('response') {\n @if(traceField(step.output, 'answer'); as answer) {\n <div class=\"trace-query\"><span>Final grounded response</span><blockquote>{{ formatTraceScalar(answer) }}</blockquote></div>\n }\n <dl class=\"trace-argument-grid\">\n @for(entry of traceEntries(step.output); track entry.key) {\n @if(entry.key !== 'answer') {\n <div><dt>{{ entry.label }}</dt><dd>{{ formatTraceScalar(entry.value) }}</dd></div>\n }\n }\n </dl>\n }\n\n @default {\n <div class=\"trace-payload-grid\">\n @if(step.input !== undefined) {\n <section><span>Input</span><pre>{{ formatTraceValue(step.input) }}</pre></section>\n }\n @if(step.output !== undefined) {\n <section><span>Output</span><pre>{{ formatTraceValue(step.output) }}</pre></section>\n }\n </div>\n }\n }\n\n @if(step.error; as error) {\n <div class=\"trace-error\" [class.trace-warning]=\"step.category === 'api_call' && isHttpSuccessful(step)\">\n <strong class=\"trace-error-heading\">\n @if(step.category === 'api_call' && isHttpSuccessful(step)) {\n Post-response processing stopped\n } @else {\n Step stopped@if(error.statusCode) { \u00B7 HTTP {{ error.statusCode }} }\n }\n </strong>\n <strong class=\"trace-error-legacy\" aria-hidden=\"true\">\n Failed@if(error.statusCode) { \u2014 HTTP {{ error.statusCode }} }\n </strong>\n <span>{{ error.message }}</span>\n </div>\n }\n </div>\n }\n </section>\n </li>\n }\n </ol>\n </section>\n </div>\n }\n }\n } @else {\n @if(message.role === 'assistant') {\n <div\n class=\"assistant-markdown\"\n [innerHTML]=\"message.content | maxAssistantMarkdown\"\n ></div>\n @if(isWelcomeState(message) && bootstrapConfig.initialDescription; as initialDescription) {\n <p class=\"welcome-description\">{{ initialDescription }}</p>\n }\n @if(isWelcomeState(message)) {\n <button\n type=\"button\"\n class=\"support-welcome-card\"\n aria-label=\"Raise a support ticket\"\n (click)=\"openSupportTicket()\"\n >\n <span class=\"support-welcome-icon\" aria-hidden=\"true\">\n <i class=\"far fa-user-headset\"></i>\n </span>\n <span class=\"support-welcome-copy\">\n <strong>Raise a support ticket</strong>\n <small>Send details directly to our support team.</small>\n </span>\n <i class=\"support-welcome-arrow pi pi-arrow-right\" aria-hidden=\"true\"></i>\n </button>\n }\n } @else {\n <p>{{ message.content }}</p>\n }\n }\n @if(message.role === 'assistant' && message.suggestions?.length) {\n @if(hasCapabilitySuggestions(message.suggestions)) {\n <div class=\"capability-options\" aria-label=\"Available Maxtime capabilities\">\n @for(group of capabilitySuggestionGroups(message.suggestions); track group.section) {\n <section class=\"capability-option-section\">\n <h3>{{ group.section }}</h3>\n <div class=\"capability-option-grid\">\n @for(suggestion of group.options; track suggestion.structuredAction?.capabilityKey ?? suggestion.label; let optionIndex = $index) {\n <button\n pButton\n type=\"button\"\n severity=\"secondary\"\n class=\"capability-option-card\"\n [disabled]=\"isSending()\"\n [attr.aria-label]=\"'Choose capability: ' + suggestion.label\"\n (click)=\"useSuggestion(suggestion)\"\n >\n <span class=\"capability-option-number\" aria-hidden=\"true\">\n {{ optionIndex + 1 }}\n </span>\n <span class=\"capability-option-copy\">{{ suggestion.label }}</span>\n <i class=\"pi pi-arrow-right capability-option-arrow\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n </section>\n }\n </div>\n } @else if(hasOptionCardSuggestions(message.suggestions, message.status)) {\n <div class=\"clarification-options\" aria-label=\"Clarification options\">\n <div class=\"capability-option-grid clarification-option-grid\">\n @for(suggestion of optionCardSuggestions(message.suggestions, message.status); track suggestionLabel(suggestion); let optionIndex = $index) {\n <button\n pButton\n type=\"button\"\n severity=\"secondary\"\n class=\"capability-option-card clarification-option-card\"\n [disabled]=\"isSending()\"\n [attr.aria-label]=\"'Choose option: ' + suggestionLabel(suggestion)\"\n (click)=\"useSuggestion(suggestion)\"\n >\n <span class=\"capability-option-number\" aria-hidden=\"true\">\n {{ optionIndex + 1 }}\n </span>\n <span class=\"capability-option-copy\">{{ suggestionLabel(suggestion) }}</span>\n <i class=\"pi pi-arrow-right capability-option-arrow\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n </div>\n } @else if(hasEntitySuggestions(message.suggestions)) {\n <div class=\"entity-options\" aria-label=\"Matching options\">\n @for(suggestion of entitySuggestionOptions(message.suggestions); track suggestion.entity.id ?? suggestion.label) {\n <max-agent-entity-option\n [entity]=\"suggestion.entity\"\n [disabled]=\"isSending()\"\n (selected)=\"useSuggestion(suggestion)\"\n ></max-agent-entity-option>\n }\n </div>\n } @else {\n <div class=\"suggestions\">\n @for(suggestion of message.suggestions ?? []; track suggestion) {\n <button\n pButton\n type=\"button\"\n size=\"small\"\n text\n severity=\"secondary\"\n class=\"suggestion-chip\"\n [label]=\"suggestionLabel(suggestion)\"\n (click)=\"useSuggestion(suggestion)\"\n ></button>\n }\n </div>\n }\n }\n @if(message.role === 'assistant' && !isWelcomeMessage(message) && !message.isStreaming) {\n <div class=\"response-actions\">\n <button\n type=\"button\"\n class=\"response-feedback-action\"\n [attr.aria-label]=\"uiCopy.feedbackLabel\"\n [pTooltip]=\"uiCopy.feedbackTooltip\"\n tooltipPosition=\"bottom\"\n (click)=\"openFeedback(message)\"\n >\n <i class=\"pi pi-comment\" aria-hidden=\"true\"></i>\n </button>\n @if(developerDetailsEnabled && message.developerTrace?.steps?.length) {\n <button\n type=\"button\"\n class=\"details-toggle\"\n [attr.aria-expanded]=\"isDetailsVisible(message.id)\"\n (click)=\"toggleDetails(message.id, message.developerTrace!.steps[0]?.id)\"\n >\n {{ isDetailsVisible(message.id) ? 'Hide Developer Trace' : 'Show Developer Trace' }}\n </button>\n }\n </div>\n }\n </article>\n }\n </div>\n\n <footer class=\"assistant-footer\">\n @if(hasConversationStarted()) {\n <button\n type=\"button\"\n class=\"support-ticket-shortcut\"\n aria-label=\"Raise a support ticket\"\n (click)=\"openSupportTicket()\"\n >\n <i class=\"far fa-user-headset\" aria-hidden=\"true\"></i>\n <span>Raise a support ticket</span>\n </button>\n }\n <form class=\"assistant-composer\" (ngSubmit)=\"sendMessage()\">\n <textarea\n #composerInput\n pTextarea\n name=\"assistantPrompt\"\n rows=\"1\"\n [placeholder]=\"uiCopy.placeholder\"\n [ngModel]=\"input()\"\n (ngModelChange)=\"input.set($event)\"\n (keydown)=\"onComposerKeydown($event)\"\n >\n </textarea>\n <button\n pButton\n type=\"submit\"\n icon=\"pi pi-send\"\n aria-label=\"Send message\"\n [disabled]=\"!input().trim() || isSending()\"\n ></button>\n </form>\n </footer>\n </section>\n\n @if(supportTicketVisible()) {\n <section class=\"support-ticket-overlay\" aria-label=\"Support ticket form\">\n <div\n class=\"support-ticket-dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"supportTicketTitle\"\n >\n <header class=\"support-ticket-header\">\n <span class=\"support-ticket-header-icon\" aria-hidden=\"true\">\n <i class=\"far fa-user-headset\"></i>\n </span>\n <div>\n <h2 id=\"supportTicketTitle\">Raise a support ticket</h2>\n <p>Share the details and our support team will take it from here.</p>\n </div>\n <button\n type=\"button\"\n class=\"support-ticket-close\"\n aria-label=\"Close support ticket form\"\n (click)=\"closeSupportTicket()\"\n >\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </header>\n\n @if(supportTicketSubmissionFailed()) {\n <div class=\"support-ticket-error-page\" role=\"alert\">\n <span class=\"support-ticket-error-icon\" aria-hidden=\"true\">\n <i class=\"pi pi-times-circle\"></i>\n </span>\n <h3>Ticket could not be created</h3>\n <p>{{ supportTicketError() }}</p>\n <button\n pButton\n type=\"button\"\n label=\"Close\"\n icon=\"pi pi-times\"\n severity=\"secondary\"\n (click)=\"closeSupportTicket()\"\n ></button>\n </div>\n } @else if(supportTicketResult(); as result) {\n <div class=\"support-ticket-success\" role=\"status\">\n <span class=\"support-ticket-success-icon\" aria-hidden=\"true\">\n <i class=\"pi pi-check\"></i>\n </span>\n <h3>Ticket raised</h3>\n <p>{{ result.message }}</p>\n @if(result.ticketReference) {\n <div class=\"support-ticket-reference\">\n <span>Reference</span>\n <strong>{{ result.ticketReference }}</strong>\n </div>\n }\n <button\n pButton\n type=\"button\"\n label=\"Done\"\n icon=\"pi pi-check\"\n (click)=\"closeSupportTicket()\"\n ></button>\n </div>\n } @else {\n <form class=\"support-ticket-form\" (ngSubmit)=\"submitSupportTicket()\">\n <div class=\"support-ticket-fields\">\n <label class=\"support-ticket-field\">\n <span>Name</span>\n <input\n type=\"text\"\n name=\"supportName\"\n autocomplete=\"name\"\n [value]=\"supportTicketForm.name\"\n readonly\n />\n </label>\n\n <label class=\"support-ticket-field\">\n <span>Email</span>\n <input\n type=\"email\"\n name=\"supportEmail\"\n autocomplete=\"email\"\n [value]=\"supportTicketForm.email\"\n readonly\n />\n </label>\n\n <label class=\"support-ticket-field support-ticket-field-wide\">\n <span>Phone <small>Optional</small></span>\n <input\n type=\"tel\"\n name=\"supportPhone\"\n autocomplete=\"tel\"\n placeholder=\"Add a contact number\"\n [(ngModel)]=\"supportTicketForm.phone\"\n />\n </label>\n\n <label class=\"support-ticket-field\">\n <span>Severity</span>\n <p-select\n inputId=\"supportSeverity\"\n name=\"supportSeverity\"\n [options]=\"supportSeverities()\"\n optionLabel=\"label\"\n [fluid]=\"true\"\n [loading]=\"supportSeverities().length === 0\"\n [(ngModel)]=\"supportTicketForm.severity\"\n >\n <ng-template #selectedItem let-severity>\n <p-tag\n class=\"support-severity-tag\"\n [value]=\"severity.label\"\n [style.--support-severity-color]=\"supportSeverityColor(severity.color)\"\n [rounded]=\"true\"\n ></p-tag>\n </ng-template>\n <ng-template #item let-severity>\n <p-tag\n class=\"support-severity-option\"\n [value]=\"severity.label\"\n [style.--support-severity-color]=\"supportSeverityColor(severity.color)\"\n [rounded]=\"true\"\n ></p-tag>\n </ng-template>\n </p-select>\n </label>\n\n <label class=\"support-ticket-field\">\n <span>Tags</span>\n <p-multiselect\n inputId=\"supportTags\"\n name=\"supportTags\"\n placeholder=\"Select relevant areas\"\n [options]=\"supportTags()\"\n optionLabel=\"label\"\n dataKey=\"id\"\n display=\"chip\"\n [filter]=\"true\"\n filterBy=\"label\"\n [showToggleAll]=\"false\"\n [loading]=\"supportTagsLoading()\"\n [fluid]=\"true\"\n [(ngModel)]=\"supportTicketForm.tags\"\n >\n <ng-template #selecteditems let-selectedTags>\n <span class=\"support-selected-tags\">\n @for(tag of selectedTags; track tag.id) {\n <p-tag\n class=\"support-selected-tag\"\n [value]=\"tag.label\"\n [icon]=\"tag.icon\"\n [severity]=\"tag.severity\"\n [rounded]=\"true\"\n ></p-tag>\n }\n </span>\n </ng-template>\n <ng-template #item let-tag>\n <p-tag\n class=\"support-tag-option\"\n [value]=\"tag.label\"\n [icon]=\"tag.icon\"\n [severity]=\"tag.severity\"\n [rounded]=\"true\"\n ></p-tag>\n </ng-template>\n </p-multiselect>\n </label>\n\n <label class=\"support-ticket-field support-ticket-field-wide\">\n <span>Subject</span>\n <input\n type=\"text\"\n name=\"supportSubject\"\n maxlength=\"200\"\n placeholder=\"Summarise the issue\"\n required\n [(ngModel)]=\"supportTicketForm.subject\"\n />\n </label>\n\n <label class=\"support-ticket-field support-ticket-field-wide\">\n <span>How can we help?</span>\n <textarea\n #supportQueryInput\n pTextarea\n name=\"supportQuery\"\n rows=\"5\"\n placeholder=\"Describe the issue, what you expected, and anything you've already tried.\"\n required\n [(ngModel)]=\"supportTicketForm.query\"\n ></textarea>\n </label>\n </div>\n\n @if(!supportTicketForm.name || !supportTicketForm.email) {\n <p class=\"support-ticket-notice\" role=\"alert\">\n Your signed-in name and email are required. Please refresh your Nemesys session and try again.\n </p>\n }\n @if(supportTicketError(); as supportError) {\n <p class=\"support-ticket-error\" role=\"alert\">{{ supportError }}</p>\n }\n\n <div class=\"support-ticket-actions\">\n <button\n pButton\n type=\"button\"\n label=\"Cancel\"\n severity=\"secondary\"\n outlined\n (click)=\"closeSupportTicket()\"\n ></button>\n <button\n pButton\n type=\"submit\"\n label=\"Submit ticket\"\n icon=\"pi pi-send\"\n [loading]=\"supportTicketSubmitting()\"\n [disabled]=\"!canSubmitSupportTicket()\"\n ></button>\n </div>\n </form>\n }\n </div>\n </section>\n }\n\n @if(feedbackVisible()) {\n <section\n class=\"support-ticket-overlay feedback-overlay\"\n aria-label=\"Feedback form\"\n >\n <div\n class=\"support-ticket-dialog feedback-dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"feedbackTitle\"\n >\n <header class=\"support-ticket-header feedback-header\">\n <span class=\"support-ticket-header-icon\" aria-hidden=\"true\">\n <i class=\"pi pi-comment\"></i>\n </span>\n <div>\n <h2 id=\"feedbackTitle\">Help Max improve</h2>\n <p>Tell us what Max could do better.</p>\n </div>\n <button\n type=\"button\"\n class=\"support-ticket-close feedback-close\"\n aria-label=\"Close feedback form\"\n (click)=\"closeFeedback()\"\n >\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </header>\n\n @if(feedbackResult(); as result) {\n <div class=\"support-ticket-success feedback-success\" role=\"status\">\n <span class=\"support-ticket-success-icon\" aria-hidden=\"true\">\n <i class=\"pi pi-check\"></i>\n </span>\n <h3>Feedback received</h3>\n <p>{{ result.message }}</p>\n <div class=\"support-ticket-reference\">\n <span>Reference</span>\n <strong>{{ result.feedbackReference }}</strong>\n </div>\n <button\n pButton\n type=\"button\"\n label=\"Done\"\n icon=\"pi pi-check\"\n (click)=\"closeFeedback()\"\n ></button>\n </div>\n } @else {\n <form class=\"support-ticket-form feedback-form\" (ngSubmit)=\"submitFeedback()\">\n <div class=\"feedback-form-body\">\n <div class=\"support-ticket-fields\">\n <label class=\"support-ticket-field\">\n <span>Name</span>\n <input\n type=\"text\"\n name=\"feedbackName\"\n autocomplete=\"name\"\n [value]=\"feedbackForm.name\"\n readonly\n />\n </label>\n\n <label class=\"support-ticket-field\">\n <span>Email</span>\n <input\n type=\"email\"\n name=\"feedbackEmail\"\n autocomplete=\"email\"\n [value]=\"feedbackForm.email\"\n readonly\n />\n </label>\n\n <label class=\"support-ticket-field\">\n <span>Phone <small>Optional</small></span>\n <input\n type=\"tel\"\n name=\"feedbackPhone\"\n autocomplete=\"tel\"\n placeholder=\"Add a contact number\"\n [(ngModel)]=\"feedbackForm.phone\"\n />\n </label>\n\n <label class=\"support-ticket-field\">\n <span>Feedback type</span>\n <p-select\n inputId=\"feedbackCategory\"\n name=\"feedbackCategory\"\n [options]=\"feedbackCategoryOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [fluid]=\"true\"\n [(ngModel)]=\"feedbackForm.category\"\n ></p-select>\n </label>\n\n <label class=\"support-ticket-field support-ticket-field-wide\">\n <span>Your query</span>\n <textarea\n pTextarea\n name=\"feedbackQuery\"\n rows=\"2\"\n placeholder=\"Enter the question or request you gave Max.\"\n readonly\n required\n [(ngModel)]=\"feedbackForm.query\"\n ></textarea>\n </label>\n\n <label class=\"support-ticket-field support-ticket-field-wide\">\n <span>Assistant response <small>Added automatically when available</small></span>\n <textarea\n pTextarea\n name=\"feedbackAssistantResponse\"\n rows=\"3\"\n placeholder=\"No assistant response is available yet.\"\n [value]=\"feedbackForm.assistantResponse\"\n readonly\n ></textarea>\n </label>\n\n <label class=\"support-ticket-field support-ticket-field-wide\">\n <span>What could be improved?</span>\n <textarea\n #feedbackInput\n pTextarea\n name=\"feedbackDetails\"\n rows=\"3\"\n placeholder=\"Tell us what you expected, what was missing, or how the response could be more useful.\"\n required\n [(ngModel)]=\"feedbackForm.feedback\"\n ></textarea>\n </label>\n </div>\n\n @if(!feedbackForm.name || !feedbackForm.email) {\n <p class=\"support-ticket-notice\" role=\"alert\">\n Your signed-in name and email are required. Please refresh your Nemesys session and try again.\n </p>\n }\n @if(feedbackError(); as error) {\n <p class=\"support-ticket-error\" role=\"alert\">{{ error }}</p>\n }\n </div>\n\n <footer class=\"support-ticket-actions feedback-actions\">\n <button\n pButton\n type=\"button\"\n label=\"Cancel\"\n severity=\"secondary\"\n outlined\n (click)=\"closeFeedback()\"\n ></button>\n <button\n pButton\n type=\"submit\"\n label=\"Send feedback\"\n icon=\"pi pi-send\"\n [loading]=\"feedbackSubmitting()\"\n [disabled]=\"!canSubmitFeedback()\"\n ></button>\n </footer>\n </form>\n }\n </div>\n </section>\n }\n</aside>\n", styles: [":host{position:relative;display:block;width:100%;height:100%;min-height:0}.assistant-launcher{position:relative;width:64px!important;height:64px!important;min-height:64px!important;padding:7px;border:1px solid rgba(124,58,237,.24)!important;border-radius:22px!important;color:inherit!important;background:radial-gradient(circle at 28% 16%,rgba(255,255,255,.98),transparent 38%),linear-gradient(145deg,#fff7ed,#f5f3ff 52%,#fdf2f8)!important;box-shadow:0 0 0 1px #ffffffd9 inset,0 12px 30px #5b21b62e!important;overflow:visible;transition:border-color .22s ease,box-shadow .22s ease,transform .22s cubic-bezier(.2,.8,.2,1);z-index:2}.assistant-launcher:before,.assistant-launcher:after{content:\"\";position:absolute;top:50%;left:50%;width:22px;height:2px;border-radius:999px;background:#0f6cae;opacity:0;transform:translate(-50%,-50%) scale(.6) rotate(0);transition:opacity .18s ease,transform .22s ease;z-index:1}.assistant-launcher:before{transform:translate(-50%,-50%) scale(.6) rotate(45deg)}.assistant-launcher:after{transform:translate(-50%,-50%) scale(.6) rotate(-45deg)}.assistant-launcher:hover,.assistant-launcher:focus-visible{border-color:#ec489975!important;background:radial-gradient(circle at 30% 18%,#fff,transparent 38%),linear-gradient(145deg,#ffedd5,#ede9fe,#fce7f3)!important;box-shadow:0 0 0 3px #a855f71a,0 16px 34px #6d28d938!important;transform:translateY(-2px)}.assistant-launcher.is-open{background:#fff!important;box-shadow:0 0 0 2px #0078c838,0 14px 32px #0f172a2e!important;transform:translateY(0)}.assistant-launcher.is-open:before,.assistant-launcher.is-open:after{opacity:1}.assistant-launcher.is-open:before{transform:translate(-50%,-50%) scale(1) rotate(45deg)}.assistant-launcher.is-open:after{transform:translate(-50%,-50%) scale(1) rotate(-45deg)}.mascot{position:relative;display:inline-grid;width:54px;height:54px;place-items:center;transform-origin:50% 72%;transition:opacity .18s ease,transform .24s ease,filter .24s ease;z-index:0}.mascot-aura{position:absolute;inset:5px;border-radius:50%;background:conic-gradient(from 25deg,#f472b66b,#fbbf2452,#2dd4bf57,#8b5cf66b,#f472b66b);filter:blur(7px);animation:mascot-aura 3s ease-in-out infinite}.mascot-art{position:relative;width:100%;height:100%;overflow:visible;filter:drop-shadow(0 5px 5px rgba(2,75,116,.2));animation:mascot-idle 3.4s ease-in-out infinite}.mascot-shell{fill:#7c3aed}.mascot-ear-left{fill:#ec4899}.mascot-ear-right{fill:#f97316}.mascot-ear{transform-box:fill-box;transform-origin:center}.mascot-face{fill:#211747;stroke:#ffffff4d;stroke-width:1}.mascot-signal{fill:#facc15;stroke:#fff;stroke-width:1.5;transform-box:fill-box;transform-origin:center;animation:mascot-signal 2.2s ease-out infinite}.mascot-antenna,.mascot-sparkle,.mascot-shell-shine,.mascot-smile,.mascot-mark{fill:none;stroke-linecap:round;stroke-linejoin:round}.mascot-antenna{stroke:#6d28d9;stroke-width:2.5}.mascot-sparkle{stroke:#ec4899;stroke-width:2;transform-box:fill-box;transform-origin:center;animation:mascot-sparkle 3.4s ease-in-out infinite}.mascot-shell-shine{stroke:#e9d5ffd1;stroke-width:2}.mascot-eye{fill:#5eead4;transform-box:fill-box;transform-origin:center;animation:mascot-blink 5.2s ease-in-out infinite}.mascot-smile{stroke:#fbbf24;stroke-width:2}.mascot-mark{stroke:#ffffffd1;stroke-width:2.2}.assistant-launcher:hover .mascot-art,.assistant-launcher:focus-visible .mascot-art{animation:mascot-greet .7s cubic-bezier(.2,.8,.2,1)}.assistant-launcher:hover .mascot-ear-right,.assistant-launcher:focus-visible .mascot-ear-right{animation:mascot-ear-wave .7s ease-in-out}.assistant-launcher.is-open .mascot{filter:saturate(1.08);opacity:.24;transform:scale(.82) rotate(-5deg)}.mascot.large{width:52px;height:52px;flex:0 0 auto}@keyframes mascot-idle{0%,to{transform:translateY(0) rotate(0)}50%{transform:translateY(-2px) rotate(1deg)}}@keyframes mascot-greet{0%,to{transform:translateY(0) rotate(0)}35%{transform:translateY(-4px) rotate(-5deg)}65%{transform:translateY(-2px) rotate(4deg)}}@keyframes mascot-ear-wave{0%,to{transform:rotate(0) scaleY(1)}50%{transform:rotate(-12deg) scaleY(1.12)}}@keyframes mascot-blink{0%,45%,49%,to{transform:scaleY(1)}47%{transform:scaleY(.12)}}@keyframes mascot-signal{0%,55%,to{opacity:1;transform:scale(1)}70%{opacity:.55;transform:scale(1.42)}}@keyframes mascot-sparkle{0%,62%,to{opacity:0;transform:scale(.5) rotate(0)}72%{opacity:1;transform:scale(1) rotate(90deg)}84%{opacity:0;transform:scale(.7) rotate(150deg)}}@keyframes mascot-aura{0%,to{opacity:.45;transform:scale(.88)}50%{opacity:.85;transform:scale(1.08)}}.assistant-window{position:relative;width:100%;height:100%;min-height:0;border:1px solid rgba(148,163,184,.24);border-radius:24px;background:#fffffff5;box-shadow:0 24px 70px #0f172a33,0 0 0 1px #ffffffad inset;overflow:hidden;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.assistant-panel{display:grid;grid-template-rows:auto 1fr auto;height:100%;min-height:0;border-radius:inherit;background:linear-gradient(180deg,#f8fafcd1,#f1f5f9f5),var(--max-canvas, #f8fafc);overflow:hidden}.assistant-header,.assistant-composer{display:flex;gap:12px;align-items:center;padding:16px 18px;background:#ffffffeb;border-bottom:1px solid rgba(226,232,240,.86)}.assistant-identity{display:grid;gap:5px;min-width:0}.assistant-name{margin:0;width:fit-content;color:var(--max-accent, #2563eb);font:inherit;font-weight:600}.assistant-subtitle{color:#64748b;font-size:10px;font-weight:600;letter-spacing:.1em;line-height:1.2;text-transform:uppercase}.sources span{color:#64748b;font-size:12px;font-weight:600}.assistant-header .header-action:first-of-type{margin-left:auto}.assistant-header .header-action{width:38px;height:38px;margin-left:0;color:#475569;background:transparent}.assistant-header .header-action:hover{background:#0f172a0f}.assistant-messages{min-height:0;overflow:auto;padding:18px;scrollbar-width:thin}.assistant-messages,.assistant-table-wrap,.assistant-rota-scroll{scrollbar-color:#cbd5e1 transparent;scrollbar-width:thin}.assistant-messages::-webkit-scrollbar,.assistant-table-wrap::-webkit-scrollbar,.assistant-rota-scroll::-webkit-scrollbar{width:6px;height:6px}.assistant-messages::-webkit-scrollbar-track,.assistant-table-wrap::-webkit-scrollbar-track,.assistant-rota-scroll::-webkit-scrollbar-track{background:transparent}.assistant-messages::-webkit-scrollbar-thumb,.assistant-table-wrap::-webkit-scrollbar-thumb,.assistant-rota-scroll::-webkit-scrollbar-thumb{border-radius:999px;background:#cbd5e1}.message{position:relative;width:fit-content;max-width:92%;margin-bottom:14px;padding:12px;border:1px solid var(--border-color, #e2e8f0);border-radius:16px;background:#fff;box-shadow:0 1px 2px #0f172a14,0 10px 24px #0f172a0f;-webkit-user-select:text;user-select:text}.message.assistant{width:100%;max-width:100%}.message.user{width:fit-content;max-width:88%;margin-left:auto;color:#fff;background:var(--primary-color, #2563eb);border-color:var(--border-color, #e2e8f0);border-bottom-right-radius:6px}.message.user p{color:inherit}.message.error{border-color:var(--danger-color, #dc2626)}.message.streaming{padding:0;border:0;color:var(--text-color-secondary, #64748b);background:transparent;box-shadow:none;font-style:italic}.streaming-progress{background:linear-gradient(100deg,var(--max-muted, #64748b) 20%,var(--primary-color, #2563eb) 42%,#a855f7 50%,var(--primary-color, #2563eb) 58%,var(--max-muted, #64748b) 80%);background-size:220% 100%;background-clip:text;-webkit-background-clip:text;-webkit-text-fill-color:transparent;white-space:pre-line;animation:assistant-progress-shimmer 2.2s ease-in-out infinite}@keyframes assistant-progress-shimmer{0%{background-position:120% 0}to{background-position:-20% 0}}.message p{margin:0;line-height:1.45}.assistant-result{color:#1e293b}.assistant-cards{display:grid;gap:10px;margin-top:12px}.assistant-card{overflow:hidden;border:1px solid #e2e8f0;border-radius:12px;background:#fff;box-shadow:0 3px 12px #0f172a0d;font-weight:400}.assistant-card>header{display:grid;gap:3px;padding:13px 16px;border-bottom:1px solid #e2e8f0}.assistant-card-title{color:#0f172a;font-size:14px;font-weight:600}.assistant-card-subtitle,.assistant-card>footer{color:#64748b;font-size:12px}.assistant-card-metrics{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));padding:16px}.assistant-card-metric{display:grid;min-width:0;align-content:start;gap:5px}.assistant-card-metric-wide{grid-column:1/-1}.assistant-card-label{color:#64748b;font-size:11px;font-weight:500;letter-spacing:.01em;line-height:1.25}.assistant-card-value{color:#0f172a;font-size:14px;font-weight:600;line-height:1.4;overflow-wrap:anywhere}.assistant-card-metric[data-tone=positive] .assistant-card-value{color:#047857}.assistant-card-metric[data-tone=warning] .assistant-card-value{color:#b45309}.assistant-card :is(strong,b){font-weight:600}.assistant-card>footer{padding:0 16px 14px}:host ::ng-deep .assistant-markdown{line-height:1.45}:host ::ng-deep .assistant-markdown>:first-child{margin-top:0}:host ::ng-deep .assistant-markdown>:last-child{margin-bottom:0}:host ::ng-deep .assistant-markdown p{margin:0 0 8px}:host ::ng-deep .assistant-markdown ul,:host ::ng-deep .assistant-markdown ol{margin:8px 0;padding-left:22px}:host ::ng-deep .assistant-markdown li+li{margin-top:4px}:host ::ng-deep .assistant-markdown strong{font-weight:700}:host ::ng-deep .assistant-markdown code{padding:1px 4px;border-radius:4px;background:#e2e8f0;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:.9em}:host ::ng-deep .assistant-markdown a{color:var(--primary-color, #2563eb);text-decoration:underline}.assistant-status{display:inline-flex;margin-top:8px;padding:3px 8px;border-radius:999px;color:#475569;background:#e2e8f0;font-size:11px;font-weight:600;text-transform:capitalize}.pending-action{display:grid;gap:9px;margin-top:12px;padding:12px;border:1px solid #f59e0b;border-radius:12px;background:#fffbeb}.pending-action-heading{display:flex;align-items:center;justify-content:space-between;color:#92400e}.pending-action-heading span{padding:2px 7px;border-radius:999px;color:#78350f;background:#fde68a;font-size:11px;font-weight:700}.pending-action small{color:#78716c}.pending-action-buttons{display:flex;gap:8px}.action-decision{color:#475569;font-weight:600}.assistant-sources{display:grid;gap:4px;margin-top:12px;padding-top:10px;border-top:1px solid #e2e8f0;color:#64748b;font-size:12px}.assistant-shift-groups,.assistant-shift-group{display:grid;gap:10px}.assistant-shift-groups,.assistant-rota{margin-top:12px}.assistant-shift-group h3,.assistant-rota h3{margin:0;color:#0f172a;font-size:13px;font-weight:600}.assistant-shift-card-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:9px}.assistant-rota{display:grid;gap:10px}.assistant-rota-heading{display:grid;gap:8px}.assistant-rota-summary{display:flex;flex-wrap:wrap;gap:7px}.assistant-rota-summary>span{display:grid;gap:2px;min-width:86px;padding:7px 9px;border:1px solid #e2e8f0;border-radius:8px;background:#f8fafc}.assistant-rota-summary small{color:#64748b;font-size:9px;font-weight:600;text-transform:uppercase}.assistant-rota-summary strong{color:#334155;font-size:11px}.assistant-rota-scroll{max-width:100%;overflow-x:auto;border:1px solid #e2e8f0;border-radius:10px;background:#fff}.assistant-rota-week{min-width:1288px}.assistant-rota-week+.assistant-rota-week{border-top:1px solid #cbd5e1}.assistant-rota-week-heading{display:flex;align-items:center;justify-content:space-between;padding:8px 10px;color:#334155;background:#f1f5f9}.assistant-rota-week-heading strong{font-size:12px}.assistant-rota-week-heading span{color:#64748b;font-size:10px}.assistant-rota-week-grid{display:grid;grid-template-columns:repeat(7,minmax(184px,1fr))}.assistant-rota-day{min-width:0;min-height:120px;border-right:1px solid #e2e8f0}.assistant-rota-day:last-child{border-right:0}.assistant-rota-day>header{display:flex;align-items:baseline;justify-content:space-between;padding:7px 8px;border-bottom:1px solid #e2e8f0;color:#334155;background:#f8fafc}.assistant-rota-day>header strong{font-size:10px}.assistant-rota-day>header span{color:#64748b;font-size:9px}.assistant-rota-day-shifts{display:grid;gap:7px;padding:7px}.assistant-rota-empty,.assistant-rota-no-weeks{margin:0;color:#94a3b8;font-size:10px;font-style:italic}.assistant-visualisations{display:grid;gap:10px;margin-top:12px}.assistant-visualisation{display:grid;gap:12px;padding:13px;border:1px solid #dbeafe;border-radius:14px;background:linear-gradient(145deg,#f8fbff,#fff)}.assistant-visualisation h3{margin:0;color:#0f172a;font-size:13px;font-weight:600}.assistant-export-heading{display:flex;min-width:0;gap:8px;align-items:center}.assistant-export-heading h3{min-width:0}.assistant-export-action{flex:0 0 auto;margin-left:auto;padding:0;color:inherit;background:transparent;border-color:transparent;box-shadow:none}:host ::ng-deep .assistant-export-action .p-button-icon{font-size:20px!important}.assistant-export-action-pdf{color:#d32f2f}.assistant-export-action-excel{color:#217346}.assistant-export-action-pdf:hover{color:#b71c1c;background:transparent;border-color:transparent}.assistant-export-action-excel:hover{color:#185c37;background:transparent;border-color:transparent}.assistant-doughnut-layout{display:grid;grid-template-columns:112px minmax(0,1fr);gap:14px;align-items:center}.assistant-doughnut{position:relative;display:grid;place-items:center;width:112px;aspect-ratio:1}.assistant-doughnut svg{width:100%;height:100%;transform:rotate(-90deg)}.assistant-doughnut circle{fill:none;stroke-width:6}.assistant-doughnut-track{stroke:#e2e8f0}.assistant-doughnut-segment{transition:stroke-dasharray .18s ease}.assistant-doughnut>span{position:absolute;display:grid;color:#64748b;font-size:9px;line-height:1.1;text-align:center}.assistant-doughnut>span strong{color:#0f172a;font-size:18px}.assistant-chart-legend{display:grid;gap:7px;min-width:0}.assistant-chart-legend-item{display:grid;grid-template-columns:9px minmax(0,1fr) auto;gap:7px;align-items:center;color:#475569;font-size:11px}.assistant-chart-legend-item i{width:9px;height:9px;border-radius:999px}.assistant-chart-legend-item strong,.assistant-bar-label strong{color:#0f172a;font-size:11px;font-weight:600}.assistant-bar-chart,.assistant-bar-row{display:grid;gap:6px}.assistant-bar-chart{gap:11px}.assistant-bar-label{display:flex;gap:12px;align-items:baseline;justify-content:space-between;color:#475569;font-size:11px}.assistant-bar-track{height:9px;overflow:hidden;border-radius:999px;background:#e2e8f0}.assistant-bar-track i{display:block;height:100%;min-width:0;border-radius:var(--max-frame-radius, 0);transition:width .18s ease}.assistant-tables{display:grid;gap:10px;margin-top:12px}.assistant-table-section{display:grid;gap:6px}.assistant-table-section h3{margin:0;color:#0f172a;font-size:13px;font-weight:600}.assistant-table-wrap{overflow:auto;max-height:450px;border:1px solid var(--border-color, #e2e8f0);border-radius:var(--border-radius, 6px)}.assistant-table-wrap table{width:100%;min-width:420px;border-collapse:collapse;background:#fff}.assistant-table-wrap th,.assistant-table-wrap td{padding:8px 10px;border-bottom:1px solid var(--border-color, #e2e8f0);color:#334155;font-size:12px;line-height:1.35;text-align:left;vertical-align:top}.assistant-table-wrap th{position:sticky;z-index:1;top:0;color:#475569;font-weight:600;background:#f8fafc}.assistant-table-wrap tr:last-child td{border-bottom:0}.assistant-table-actions{display:flex;flex-wrap:wrap;gap:6px;min-width:150px}.assistant-table-pagination{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px;color:#64748b;font-size:12px}.assistant-table-page-error{margin:0;color:#b91c1c;font-size:12px}.details-toggle{display:flex;width:fit-content;margin:10px 0 0 auto;padding:0;border:0;color:var(--primary-color, #2563eb);background:transparent;font:inherit;font-size:13px;font-weight:400;text-decoration:underline;text-underline-offset:3px;cursor:pointer}.details-toggle:hover{color:var(--primary-dark-color, #1d4ed8)}.details-toggle:focus-visible{outline:2px solid var(--primary-color, #2563eb);outline-offset:3px}.developer-details{display:grid;gap:12px;margin-top:12px;padding:12px;border:1px solid var(--border-color, #e2e8f0);border-radius:10px;background:#f8fafc}.developer-details-header h3,.developer-details-header p{margin:0}.developer-details-header h3{color:#0f172a;font-size:13px;font-weight:600}.developer-details-header p{margin-top:2px;color:#64748b;font-size:11px}.workflow-trace{display:grid;gap:0;margin:0;padding:0;list-style:none}.workflow-step{display:block;min-width:0}.workflow-category{color:#64748b;font-size:9px;font-weight:600;letter-spacing:.06em;text-transform:uppercase}.workflow-meta{display:grid;flex:0 0 auto;gap:2px;justify-items:end;color:#64748b;font-size:9px}.workflow-status{padding:2px 5px;border-radius:999px;color:#334155;background:#e2e8f0;font-weight:600;text-transform:capitalize}.workflow-step[data-status=succeeded] .workflow-status{color:#166534;background:#dcfce7}.workflow-step[data-status=failed] .workflow-status{color:#991b1b;background:#fee2e2}.trace-json{display:grid;gap:4px;margin-top:8px}.trace-json>span{color:#64748b;font-size:10px;font-weight:600;text-transform:uppercase}.trace-json pre{max-height:280px;margin:0;padding:8px;overflow:auto;border-radius:6px;color:#dbeafe;background:#0f172a;font-size:10px;line-height:1.45;white-space:pre-wrap;overflow-wrap:anywhere}.trace-error{display:grid;gap:3px;margin-top:8px;padding:8px;border-left:3px solid #dc2626;border-radius:4px;color:#991b1b;background:#fef2f2;font-size:11px}.developer-details-header{display:flex;gap:12px;align-items:flex-start;justify-content:space-between}.developer-eyebrow{color:var(--text-color, #0f172a);font-size:9px;font-weight:600;letter-spacing:.08em;text-transform:uppercase}.trace-section-label{color:var(--text-color, #0f172a);font-size:9px;font-weight:600;text-decoration:underline;text-underline-offset:3px}.trace-run-summary{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:7px}.trace-metric{display:grid;gap:3px;min-width:0;padding:9px;border:1px solid #e2e8f0;border-radius:8px;background:#fff}.trace-metric span,.trace-loop-policy span{color:#64748b;font-size:9px;font-weight:600}.trace-metric strong{color:#0f172a;font-size:13px}.trace-loop-policy{display:grid;grid-template-columns:minmax(0,1fr) auto;grid-column:1/-1;gap:5px 12px;align-items:center;padding:10px;border:1px solid #c7d2fe;border-radius:9px;background:#eef2ff}.trace-loop-policy div{display:grid;gap:2px}.trace-loop-policy strong{color:#312e81;font-size:11px}.trace-loop-policy p{grid-column:1/-1;margin:0;color:#475569;font-size:10px;line-height:1.45}.trace-no-loop{padding:3px 7px;border-radius:999px;color:#166534!important;background:#dcfce7;font-weight:600!important}.workflow-summary{margin:9px 0 0;color:#475569;font-size:10.5px;line-height:1.5}.trace-technology{display:grid;gap:6px;margin-top:10px;padding:8px;border:1px solid #dbeafe;border-radius:7px;background:#f8fbff}.trace-inline-facts{display:flex;flex-wrap:wrap;gap:5px}.trace-inline-facts>span{display:grid;gap:1px;max-width:100%;padding:4px 6px;border-radius:5px;color:#1e293b;background:#fff;font-size:9.5px;overflow-wrap:anywhere}.trace-inline-facts small{color:#64748b;font-size:8px;font-weight:600;text-transform:uppercase}.trace-control{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:4px 8px;margin-top:8px;padding:8px;border-left:3px solid #8b5cf6;border-radius:5px;background:#f5f3ff}.trace-control>div{display:grid;gap:2px}.trace-control strong,.trace-control>span{color:#5b21b6;font-size:9.5px}.trace-control p{grid-column:1/-1;margin:0;color:#475569;font-size:9.5px;line-height:1.4}.trace-query,.trace-section,.trace-arguments,.trace-ranking-wrap{display:grid;gap:5px;margin-top:10px}.trace-query>span,.trace-transform>div>span,.trace-vector>span,.trace-payload-grid section>span,.trace-tool-call>span,.trace-supabase-call span,.trace-decision>span{color:#64748b;font-size:9px;font-weight:600;text-transform:uppercase}.trace-query>span,.trace-vector>span,.trace-payload-grid section>span,.trace-tool-call>span,.trace-decision>span{color:var(--text-color, #0f172a);text-decoration:underline;text-underline-offset:3px}.trace-query blockquote{margin:0;padding:8px 10px;border-left:3px solid #2563eb;border-radius:5px;color:#172554;background:#eff6ff;font-size:11px;font-weight:600;line-height:1.45}.trace-query-compact blockquote{border-color:#8b5cf6;color:#4c1d95;background:#f5f3ff}.trace-card-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:7px;margin-top:9px}.trace-data-card{min-width:0;padding:8px;border:1px solid #e2e8f0;border-radius:7px;background:#f8fafc}.trace-data-card-accent{border-color:#bfdbfe;background:#eff6ff}.trace-data-card h5{margin:0 0 5px;color:var(--text-color, #0f172a);font-size:10px;font-weight:600;text-decoration:underline;text-underline-offset:3px}.trace-field-list,.trace-argument-grid{display:grid;gap:4px;margin:0}.trace-field-list>div{display:grid;grid-template-columns:minmax(70px,.7fr) minmax(0,1.3fr);gap:6px}.trace-field-list dt,.trace-argument-grid dt{color:#64748b;font-size:8.5px}.trace-field-list dd,.trace-argument-grid dd{margin:0;color:#1e293b;font-size:9px;font-weight:600;overflow-wrap:anywhere}.trace-transform{display:grid;grid-template-columns:minmax(0,1fr) 18px minmax(0,1fr);gap:6px;align-items:stretch;margin-top:10px}.trace-transform>div{display:grid;gap:5px;padding:9px;border:1px solid #e2e8f0;border-radius:7px;background:#f8fafc}.trace-transform .trace-transform-result{border-color:#bfdbfe;background:#eff6ff}.trace-transform p{margin:0;color:#1e293b;font-size:10px;font-weight:600;line-height:1.4}.trace-transform-arrow{display:grid;place-items:center;color:#2563eb;font-size:16px;font-weight:600}.trace-entity-list{display:flex;flex-wrap:wrap;gap:5px}.trace-entity-list>span{display:flex;gap:5px;align-items:center;padding:4px 7px;border:1px solid #fed7aa;border-radius:999px;color:#9a3412;background:#fff7ed;font-size:9.5px}.trace-entity-list small{color:#c2410c;font-size:7.5px;font-weight:600;text-transform:uppercase}.trace-stat-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px;margin-top:8px}.trace-stat-grid>div{display:grid;gap:2px;padding:7px;border:1px solid #e2e8f0;border-radius:6px}.trace-stat-grid span{color:#64748b;font-size:8.5px}.trace-stat-grid strong{color:#0f172a;font-size:10px;overflow-wrap:anywhere}.trace-vector{display:grid;gap:4px;margin-top:7px}.trace-vector code{padding:7px;overflow:auto;border-radius:5px;color:#c4b5fd;background:#1e1b4b;font-size:8.5px;white-space:nowrap}.trace-supabase-call{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px;margin-top:10px;padding:9px;border:1px solid #a7f3d0;border-radius:7px;background:#ecfdf5}.trace-supabase-call>div{display:grid;gap:2px}.trace-supabase-call strong{color:#065f46;font-size:10px;overflow-wrap:anywhere}.trace-table-list{grid-column:1/-1}.trace-table-list>div{display:flex;flex-wrap:wrap;gap:4px}.trace-table-list code{padding:3px 5px;border-radius:4px;color:#065f46;background:#d1fae5;font-size:8.5px}.trace-decision{display:grid;gap:4px;margin-top:7px;padding:9px;border-left:3px solid #16a34a;border-radius:5px;background:#f0fdf4}.trace-decision strong{color:#14532d;font-size:11px}.trace-decision div{display:flex;flex-wrap:wrap;gap:8px;color:#166534;font-size:8.5px}.trace-ranking-wrap{overflow:auto}.trace-ranking{width:100%;min-width:610px;border-collapse:collapse;font-size:8.5px}.trace-ranking th,.trace-ranking td{padding:6px;border-bottom:1px solid #e2e8f0;color:#475569;text-align:right;vertical-align:top}.trace-ranking th{color:#64748b;background:#f8fafc;font-size:8px;text-transform:uppercase}.trace-ranking th:nth-child(2),.trace-ranking td:nth-child(2){text-align:left}.trace-ranking td:nth-child(2){display:grid;gap:2px;min-width:145px}.trace-ranking strong{color:#1e293b;font-size:9px}.trace-ranking code{color:#64748b;font-size:7.5px}.trace-argument-grid{grid-template-columns:repeat(2,minmax(0,1fr));margin-top:3px}.trace-argument-grid>div{min-width:0;padding:7px;border:1px solid #e2e8f0;border-radius:6px;background:#f8fafc}.trace-tool-call,.trace-api-route{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin-top:8px;padding:8px;border-radius:6px;color:#dbeafe;background:#0f172a}.trace-tool-call>span{width:100%;color:#94a3b8}.trace-tool-call strong{color:#bfdbfe;font-size:10px}.trace-tool-call pre,.trace-payload-grid pre{width:100%;max-height:220px;margin:0;overflow:auto;color:#dbeafe;font-size:9px;line-height:1.45;white-space:pre-wrap;overflow-wrap:anywhere}.trace-api-route>code{flex:1 1 180px;color:#e2e8f0;font-size:9px;overflow-wrap:anywhere}.trace-http-method,.trace-http-status{padding:3px 6px;border-radius:4px;color:#fff;background:#2563eb;font-size:8.5px;font-weight:600}.trace-http-status.success{color:#bbf7d0;background:#166534}.trace-http-status.error{color:#fecaca;background:#991b1b}.trace-payload-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px;margin-top:7px}.trace-payload-grid section{display:grid;gap:5px;min-width:0;padding:8px;border:1px solid #334155;border-radius:6px;background:#0f172a}.trace-payload-grid section>span{color:#94a3b8}.trace-error.trace-warning{border-left-color:#f59e0b;color:#92400e;background:#fffbeb}.trace-error-legacy{display:none}.trace-error-heading{font-size:10px}.details-dialog-backdrop{position:fixed;inset:0;z-index:20;display:grid;padding:14px;place-items:center;background:#0f172a7a;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}.details-dialog-backdrop .developer-details{display:block;width:100%;max-height:100%;margin:0;padding:0 14px 14px;overflow:auto;overscroll-behavior:contain;border:0;border-radius:14px;background:#fff;box-shadow:0 24px 70px #0f172a4d}.details-dialog-backdrop .developer-details-header{position:sticky;top:0;z-index:3;margin:0 -14px 14px;padding:14px;border-bottom:1px solid #e2e8f0;background:#fffffff7;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}.details-dialog-actions{display:flex;flex:0 0 auto;gap:7px;align-items:center}.details-dialog-close{display:grid;width:30px;height:30px;padding:0;place-items:center;border:1px solid #e2e8f0;border-radius:8px;color:#475569;background:#fff;cursor:pointer}.details-dialog-close:hover{color:#0f172a;background:#f1f5f9}.details-dialog-close:focus-visible{outline:2px solid #2563eb;outline-offset:2px}.details-dialog-backdrop .trace-run-summary{margin-bottom:6px;padding-bottom:14px;border-bottom:1px solid #cbd5e1}.details-dialog-backdrop .trace-metric{padding:0 9px;border:0;border-right:1px solid #e2e8f0;border-radius:0;background:transparent}.details-dialog-backdrop .trace-metric:nth-child(4){border-right:0}.details-dialog-backdrop .trace-loop-policy{margin-top:5px;padding:9px 0 0;border:0;border-top:1px solid #e2e8f0;border-radius:0;background:transparent}.details-dialog-backdrop .workflow-trace{display:block}.details-dialog-backdrop .workflow-step{display:block;border-bottom:1px solid #cbd5e1}.workflow-section{display:block}.workflow-step-toggle{display:flex;gap:14px;align-items:center;justify-content:space-between;width:100%;padding:14px 2px;border:0;color:inherit;background:transparent;font:inherit;text-align:left;cursor:pointer}.workflow-step-toggle:hover{background:#f8fafc}.workflow-step-toggle:focus-visible{outline:2px solid #2563eb;outline-offset:-2px}.workflow-step-toggle>div:first-child{display:grid;min-width:0;gap:2px}.workflow-step-toggle h4{margin:0;color:var(--text-color, #0f172a);font-size:12px;font-weight:600;line-height:1.4;text-decoration:underline;text-decoration-color:#94a3b8;text-underline-offset:4px}.workflow-step-number{display:block;color:var(--primary-color, #2563eb);font-size:13px;font-weight:600}.workflow-expand-icon{color:#64748b;font-size:10px}.workflow-step-content{padding:0 2px 16px}.details-dialog-backdrop .workflow-summary{margin-top:0;padding-bottom:10px;border-bottom:1px solid #e2e8f0}.details-dialog-backdrop .trace-technology,.details-dialog-backdrop .trace-control{padding:9px 0;border:0;border-bottom:1px solid #e2e8f0;border-radius:0;background:transparent}.details-dialog-backdrop .trace-control{border-left:0}.details-dialog-backdrop .trace-inline-facts>span{padding:0 8px 0 0;border-right:1px solid #e2e8f0;border-radius:0;background:transparent}.details-dialog-backdrop :is(h3,h4,h5,strong,.workflow-status,.trace-section-label,.developer-eyebrow){font-weight:600!important}@media (max-width: 520px){.trace-run-summary,.trace-card-grid,.trace-stat-grid,.trace-payload-grid,.trace-argument-grid,.trace-transform{grid-template-columns:1fr}.trace-transform-arrow{transform:rotate(90deg)}}.suggestions{display:grid;gap:0;margin-top:12px}.entity-options{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin-top:12px}.suggestion-chip{justify-content:flex-start;width:100%;padding:6px 0;border:1px solid transparent;border-radius:999px;color:var(--primary-color, #2563eb);background:transparent;font-weight:600;box-shadow:none;text-align:left;transition:padding .16s ease,border-color .16s ease,background .16s ease,box-shadow .16s ease}.suggestion-chip:hover{padding:6px 12px;border-color:rgba(var(--primary-color-rgb, 37, 99, 235),.28);color:var(--primary-color, #2563eb);background:rgba(var(--primary-color-rgb, 37, 99, 235),.08);box-shadow:0 4px 14px #0f172a0f}.response-details{display:grid;gap:12px;margin-top:12px}.response-section{display:grid;gap:8px;padding-bottom:12px;border-bottom:1px solid var(--border-color, #e2e8f0)}.response-section:last-child{padding-bottom:0;border-bottom:0}.response-section h3{margin:0;color:#0f172a;font-size:13px;font-weight:600}.quoted{padding:8px 10px;border-left:5px solid var(--primary-color, #2563eb);border-radius:var(--border-radius, 6px);color:#1e293b;background:#f8fafc}.detail-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;margin:0}.detail-grid div{min-width:0;padding:8px;border-radius:var(--border-radius, 6px);background:#f8fafc}.detail-grid dt{margin-bottom:3px;color:#64748b;font-size:11px;font-weight:600;text-transform:uppercase}.detail-grid dd{margin:0;color:#334155;font-size:13px;font-weight:600;line-height:1.35;overflow-wrap:anywhere}.detail-grid dd span{display:block;margin-top:2px;color:#64748b;font-size:11px}.api-call-summary,.json-block{display:grid;gap:6px;padding:8px;border-radius:var(--border-radius, 6px);background:#f8fafc}.api-call-summary .detail-label,.json-block .detail-label{color:#64748b;font-size:11px;font-weight:600;text-transform:uppercase}.api-call-summary code{color:var(--secondary-color, #0f172a);font-weight:600;white-space:normal;word-break:break-word}.json-block pre{max-height:220px;margin:0;overflow:auto;color:#0f172a;font-size:12px;line-height:1.45;white-space:pre-wrap;overflow-wrap:anywhere}.assistant-composer{padding:14px 16px 16px;border-top:1px solid rgba(226,232,240,.9);border-bottom:0;box-shadow:0 -10px 30px #0f172a0a}.assistant-composer textarea{flex:1;min-height:46px;max-height:120px;border-radius:18px;background:#fff;resize:vertical}.assistant-composer button[type=submit]{width:44px;height:44px;border-radius:16px}@keyframes pulse{to{opacity:.35;transform:translateY(-2px)}}@media (prefers-reduced-motion: reduce){.mascot-aura,.mascot-art,.mascot-eye,.mascot-signal,.mascot-sparkle,.assistant-launcher:hover .mascot-art,.assistant-launcher:focus-visible .mascot-art,.assistant-launcher:hover .mascot-ear-right,.assistant-launcher:focus-visible .mascot-ear-right{animation:none}.assistant-launcher,.mascot{transition-duration:.01ms}}@media (max-width: 640px){.assistant-messages{padding:14px}.detail-grid,.entity-options,.assistant-card-metrics{grid-template-columns:1fr}.assistant-card-metric{padding:0}}\n", ":host{--max-accent: var(--max-assistant-accent, #1a73e8);--max-accent-strong: var(--max-assistant-accent-strong, #1557b0);--max-canvas: var(--max-assistant-canvas, #f8f9fa);--max-surface: var(--max-assistant-surface, #ffffff);--max-surface-soft: color-mix(in srgb, var(--max-accent) 6%, var(--max-surface));--max-text: var(--max-assistant-text, #1f1f1f);--max-muted: var(--max-assistant-muted, #5f6368);--max-border: var(--max-assistant-border, #dfe1e5);--max-success: var(--max-assistant-success, #188038);--max-warning: var(--max-assistant-warning, #b06000);--max-danger: var(--max-assistant-danger, #b3261e);--max-support-text: var(--max-assistant-support-text, #3c4043);--max-control-radius: var(--max-assistant-control-radius, 6px);--max-frame-radius: var(--max-assistant-frame-radius, 0px);--max-sparkles-gradient: linear-gradient( 135deg, color-mix(in srgb, var(--max-accent) 58%, white) 0%, var(--max-accent) 46%, color-mix(in srgb, var(--max-accent) 55%, var(--max-accent-strong)) 72%, var(--max-accent-strong) 100% );--max-header-action-size: 40px;--max-header-content-size: 20px;--primary-color: var(--max-accent);--primary-color-rgb: var(--max-assistant-accent-rgb, 26, 115, 232);--primary-dark-color: var(--max-accent-strong);--background: var(--max-canvas);--background-color: var(--max-canvas);--panel-background: var(--max-surface);--text-color: var(--max-text);--text-color-secondary: var(--max-muted);--border-color: var(--max-border);--success-color: var(--max-success);--warning-color: var(--max-warning);--error-color: var(--max-danger);--danger-color: var(--max-danger);--border-radius: var(--max-control-radius);position:relative;display:block;width:100%;height:100%;min-height:0;isolation:isolate;color:var(--max-text);font-family:Arial,Helvetica,sans-serif;font-size:16px;font-weight:400;line-height:normal;text-align:left;color-scheme:light}:host,:host *{box-sizing:border-box}:host button,:host ::ng-deep .p-button-label{text-transform:capitalize}.max-assistant-sparkles{display:inline-flex;flex:0 0 auto;align-items:center;justify-content:center;font-size:var(--max-header-content-size);line-height:1;vertical-align:middle;color:transparent;background:var(--assistant-sparkles-gradient, var(--max-sparkles-gradient));background-clip:text;-webkit-background-clip:text;-webkit-text-fill-color:transparent;filter:drop-shadow(0 2px 3px rgba(60,64,67,.18))}.assistant-window{position:relative;inset:auto;width:100%;height:100%;max-height:none;overflow:hidden;opacity:1;visibility:visible;pointer-events:auto;translate:none;transform:none;border:0;border-radius:var(--max-frame-radius);background:var(--max-canvas);box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none;transition:none}.assistant-panel{grid-template-rows:72px minmax(0,1fr) auto;color:var(--max-text);background:radial-gradient(circle at 48% 0%,color-mix(in srgb,var(--max-accent) 10%,transparent),transparent 46%),radial-gradient(circle at 92% 72%,color-mix(in srgb,#c58af9 8%,transparent),transparent 38%),linear-gradient(145deg,var(--max-canvas),color-mix(in srgb,var(--max-canvas) 94%,#edf3ff))}.assistant-header{display:flex;gap:20px;align-items:center;padding:0 24px;border:0;border-bottom:1px solid var(--max-border);background:color-mix(in srgb,var(--max-canvas) 88%,transparent);-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px)}.assistant-header-actions{display:flex;gap:4px;align-items:center;margin-left:auto}.assistant-identity{display:flex;flex-direction:column}.assistant-name{align-self:flex-start;margin:0;color:transparent;background:var(--assistant-sparkles-gradient, var(--max-sparkles-gradient));background-clip:text;-webkit-background-clip:text;-webkit-text-fill-color:transparent;font:inherit;font-size:var(--max-header-content-size);font-weight:600;line-height:1}.assistant-subtitle{color:var(--max-muted);font-size:12px;font-weight:400;letter-spacing:0;line-height:1;text-transform:none}.assistant-name-row{display:flex;align-items:center;gap:8px}.assistant-beta-tag{padding:3px 6px;color:var(--max-text-color, #475569);font-size:11px;font-weight:700;line-height:1;background:var(--max-accent-color, #e2e8f0);border-radius:4px}.assistant-header .header-action{display:inline-flex;width:var(--max-header-action-size);min-width:var(--max-header-action-size);height:var(--max-header-action-size);align-items:center;justify-content:center;margin:0;padding:0;appearance:none;border:0;border-radius:50%;color:var(--max-muted);background:transparent;font:inherit;line-height:1;cursor:pointer}.assistant-header .header-action-icon{font-size:var(--max-header-content-size);font-weight:400;line-height:1}.assistant-header .header-action:hover{color:var(--max-text);background:var(--max-surface-soft)}.assistant-header .header-action:focus-visible{outline:2px solid var(--max-accent);outline-offset:2px}.assistant-messages{width:min(820px,100%);min-height:0;justify-self:center;box-sizing:border-box;padding:44px 28px 32px;overflow-x:hidden;overflow-y:auto;scrollbar-color:color-mix(in srgb,var(--max-muted) 25%,transparent) transparent;scrollbar-width:thin}.assistant-table-wrap,.assistant-rota-scroll{scrollbar-color:color-mix(in srgb,var(--max-muted) 25%,transparent) transparent;scrollbar-width:thin}.assistant-messages::-webkit-scrollbar-thumb,.assistant-table-wrap::-webkit-scrollbar-thumb,.assistant-rota-scroll::-webkit-scrollbar-thumb{background:color-mix(in srgb,var(--max-muted) 25%,transparent)}.message{width:100%;max-width:100%;box-sizing:border-box;margin:0 0 34px;padding:0;border:0;border-radius:0;color:var(--max-text);background:transparent;box-shadow:none}.message.assistant{width:100%;max-width:100%}.message.user{width:fit-content;max-width:min(76%,640px);margin:0 0 32px auto;padding:13px 18px;border:1px solid var(--max-border);border-radius:18px 18px 6px;color:var(--max-text);background:linear-gradient(135deg,color-mix(in srgb,var(--max-accent) 10%,var(--max-surface)),color-mix(in srgb,var(--max-accent) 5%,var(--max-surface)));box-shadow:0 1px 2px color-mix(in srgb,var(--max-text) 7%,transparent),0 6px 18px color-mix(in srgb,var(--max-accent) 8%,transparent)}.message.user p{color:inherit;font-size:15px;line-height:1.55}.message.error{padding-left:16px;border-left:3px solid var(--max-danger)}.message.streaming{display:flex;gap:10px;align-items:center;padding:0;color:var(--max-muted);background:transparent;font-style:normal}.message.streaming:before{width:16px;height:16px;flex:0 0 auto;border-radius:6px;background:var(--assistant-sparkles-gradient, var(--max-sparkles-gradient));content:\"\";animation:max-thinking 1.4s ease-in-out infinite alternate}.streaming-progress{color:var(--max-muted);font-size:14px;white-space:pre-line}.message p,.assistant-result,:host ::ng-deep .assistant-markdown{color:var(--max-text);font-size:15px;line-height:1.65}:host ::ng-deep .assistant-markdown code{color:var(--max-text);background:color-mix(in srgb,var(--max-muted) 10%,transparent)}.message.welcome{min-height:260px;margin:0;padding-top:clamp(28px,8vh,90px);text-align:center}.message.welcome .assistant-markdown{max-width:650px;margin:0 auto}:host ::ng-deep .message.welcome .assistant-markdown p{margin:0;font-size:clamp(28px,3.2vw,42px);font-weight:500;letter-spacing:-.04em;line-height:1.18}:host ::ng-deep .message.welcome-message .assistant-markdown p{color:var(--max-accent)}.welcome-description{max-width:620px;margin:0 auto!important;margin-top:2rem!important;color:var(--max-text);font-size:16px;line-height:1.6;white-space:pre-line}.support-welcome-card{display:flex;width:min(460px,100%);min-height:70px;gap:13px;align-items:center;margin:22px auto 0;padding:13px 16px;appearance:none;border:1px solid color-mix(in srgb,var(--max-accent) 24%,var(--max-border));border-radius:16px;color:var(--max-support-text);background:linear-gradient(135deg,color-mix(in srgb,var(--max-accent) 10%,var(--max-surface)),var(--max-surface) 58%);box-shadow:0 8px 28px #3c40431a;font:inherit;text-align:left;cursor:pointer;transition:border-color .16s ease,box-shadow .16s ease,transform .16s ease}.support-welcome-card:hover{border-color:color-mix(in srgb,var(--max-accent) 48%,var(--max-border));box-shadow:0 12px 32px #3c404324;transform:translateY(-1px)}.support-welcome-card:focus-visible,.support-ticket-shortcut:focus-visible,.support-ticket-close:focus-visible,.response-feedback-action:focus-visible{outline:2px solid var(--max-accent);outline-offset:2px}.support-welcome-icon,.support-ticket-header-icon,.support-ticket-success-icon{display:inline-flex;width:40px;height:40px;flex:0 0 40px;align-items:center;justify-content:center;border-radius:13px;color:var(--max-accent);background:color-mix(in srgb,var(--max-accent) 13%,var(--max-surface));font-size:18px}.support-welcome-copy{display:flex;min-width:0;flex:1;flex-direction:column;gap:5px}.support-welcome-copy strong{color:var(--max-support-text);font-size:15px;font-weight:600;line-height:1.25}.support-welcome-copy small{color:var(--max-muted);font-size:12px;line-height:1.45}.support-welcome-arrow{flex:0 0 auto;color:var(--max-accent);font-size:16px}@media (min-width: 641px) and (max-height: 850px){.message.welcome{min-height:0;padding-top:22px;padding-bottom:22px}:host ::ng-deep .message.welcome .assistant-markdown p{font-size:clamp(24px,3vw,34px)}.welcome-description{margin-top:1rem!important;font-size:14px;line-height:1.45}.support-welcome-card{min-height:58px;margin-top:14px;padding:10px 13px}}.assistant-cards{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin-top:20px}.assistant-card{overflow:hidden;border:1px solid var(--max-border);border-radius:18px;background:var(--max-surface);box-shadow:none}.assistant-card>header{gap:4px;padding:16px;border-bottom:1px solid var(--max-border)}.assistant-card>header strong{color:var(--max-text);font-size:15px;font-weight:600}.assistant-card>header span,.assistant-card>footer,.assistant-card-metric span{color:var(--max-muted)}.assistant-card-metric{padding:14px;border-color:var(--max-border)}.assistant-card-metric strong{color:var(--max-text);font-size:10px}.assistant-card-metric[data-tone=positive] strong{color:var(--max-success)}.assistant-card-metric[data-tone=warning] strong{color:var(--max-warning)}.assistant-card>footer{padding:10px 16px;border-color:var(--max-border);background:var(--max-surface-soft)}.assistant-search-result>header{display:flex;gap:12px;align-items:center}.assistant-search-result-icon{display:inline-flex;width:36px;height:36px;flex:0 0 36px;align-items:center;justify-content:center;border-radius:12px;color:var(--max-accent);background:var(--max-surface-soft);font-size:16px;font-weight:400;line-height:1}.assistant-search-result-copy{display:grid;min-width:0;gap:4px}.assistant-search-result .suggestions{display:grid;grid-template-columns:repeat(auto-fit,minmax(132px,1fr));gap:10px;margin:0;padding:16px}.assistant-search-result .suggestion-chip{width:100%;min-height:44px;align-items:center;justify-content:flex-start;padding:10px 14px;border-color:var(--max-border);background:var(--max-surface-soft);line-height:1.25}.assistant-search-result .suggestion-chip:hover{padding:10px 14px;background:color-mix(in srgb,var(--max-accent) 10%,var(--max-surface))}:host ::ng-deep .assistant-search-result .suggestion-chip .p-button-icon{font-weight:400;line-height:1}.assistant-status{margin-top:12px;padding:0;border-radius:0;color:var(--max-muted);background:transparent;font-size:11px;letter-spacing:.05em;text-transform:uppercase}.pending-action{gap:12px;margin-top:18px;padding:18px;border:1px solid color-mix(in srgb,var(--max-warning) 38%,var(--max-border));border-radius:18px;background:color-mix(in srgb,var(--max-warning) 6%,var(--max-surface))}.pending-action-heading{color:var(--max-text)}.pending-action-heading span{color:var(--max-warning);background:transparent}.pending-action small,.action-decision{color:var(--max-muted)}.assistant-sources{margin-top:20px;padding-top:14px;border-color:var(--max-border);color:var(--max-muted)}.assistant-shift-groups,.assistant-rota{margin-top:20px}.assistant-shift-group h3,.assistant-rota h3,.assistant-rota-summary strong,.assistant-rota-week-heading,.assistant-rota-day>header{color:var(--max-text)}.assistant-rota-summary>span,.assistant-rota-scroll{border-color:var(--max-border);background:var(--max-surface)}.assistant-rota-summary small,.assistant-rota-week-heading span,.assistant-rota-day>header span{color:var(--max-muted)}.assistant-rota-week-heading,.assistant-rota-day>header{background:var(--max-surface-soft)}.assistant-rota-week+.assistant-rota-week,.assistant-rota-day,.assistant-rota-day>header{border-color:var(--max-border)}.assistant-visualisations{grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin-top:20px}.assistant-visualisation{padding:16px;border-color:var(--max-border);border-radius:18px;background:var(--max-surface)}.assistant-visualisation h3,.assistant-doughnut>span strong,.assistant-chart-legend-item strong,.assistant-bar-label strong{color:var(--max-text)}.assistant-chart-legend-item,.assistant-bar-label,.assistant-doughnut>span{color:var(--max-muted)}.assistant-doughnut-track,.assistant-bar-track{stroke:var(--max-border);background:var(--max-border)}.sources span{color:var(--max-muted)}.assistant-tables{gap:18px;margin-top:20px}.assistant-table-section{gap:10px}.assistant-table-section h3{color:var(--max-text);font-size:14px}.assistant-table-wrap{border-color:var(--max-border);border-radius:16px}.assistant-table-wrap table{background:var(--max-surface)}.assistant-table-wrap th,.assistant-table-wrap td{padding:11px 13px;border-color:var(--max-border);color:var(--max-text);font-size:12px}.assistant-table-wrap th{color:var(--max-muted);background:var(--max-surface-soft)}.details-toggle{margin:0 0 0 auto;color:var(--max-accent);font-size:12px;text-decoration:underline;text-underline-offset:3px}.details-toggle:hover{color:var(--max-accent-strong);text-decoration:underline}.suggestions{display:flex;flex-wrap:wrap;gap:8px;margin-top:18px}.capability-options{display:grid;gap:22px;margin-top:18px}.clarification-options{margin-top:18px}.capability-option-section{display:grid;gap:10px}.capability-option-section h3{margin:0;color:var(--max-text);font-size:14px;font-weight:600}.capability-option-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}.capability-option-card{display:grid;grid-template-columns:auto minmax(0,1fr) auto;gap:10px;width:100%;min-height:76px;padding:12px 14px;align-items:center;border:1px solid var(--max-border);border-radius:var(--border-radius, 6px);color:var(--max-text);background:var(--max-surface);box-shadow:none;text-align:left}.capability-option-card:hover:not(:disabled){border-color:color-mix(in srgb,var(--max-accent) 32%,var(--max-border));color:var(--max-text);background:var(--max-surface-soft);box-shadow:none}.capability-option-number{display:inline-flex;min-width:24px;height:24px;align-items:center;justify-content:center;border-radius:50%;color:var(--max-accent-strong);background:var(--max-surface-soft);font-size:12px;font-weight:600}.capability-option-copy{line-height:1.4}.capability-option-arrow{color:var(--max-muted);font-size:13px}.response-actions{display:flex;align-items:center;margin-top:8px}.response-feedback-action{display:inline-flex;width:32px;height:32px;align-items:center;justify-content:center;padding:0;appearance:none;border:0;border-radius:50%;color:var(--max-muted);background:transparent;font:inherit;cursor:pointer}.response-feedback-action:hover{color:var(--max-accent);background:var(--max-surface-soft)}.suggestion-chip{justify-content:flex-start;width:auto;min-height:40px;padding:8px 14px;border:1px solid var(--max-border);border-radius:14px;color:var(--max-text);background:var(--max-surface);font-weight:400;box-shadow:none;text-align:left}.suggestion-chip:hover{padding:8px 14px;border-color:color-mix(in srgb,var(--max-accent) 28%,var(--max-border));color:var(--max-text);background:var(--max-surface-soft);box-shadow:none}.message.welcome .suggestions{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin-top:0}.message.welcome .suggestion-chip{width:100%;min-height:74px;padding:14px 16px;align-items:flex-start;border-radius:18px;line-height:1.35}.message.welcome .suggestion-chip:hover{padding:14px 16px;transform:translateY(-1px)}.assistant-footer{display:flex;width:min(780px,100% - 48px);flex-direction:column;align-items:flex-end;justify-self:center}.support-ticket-shortcut{display:inline-flex;min-height:34px;gap:7px;align-items:center;margin:0 10px 9px 0;padding:7px 12px;appearance:none;border:1px solid color-mix(in srgb,var(--max-accent) 24%,var(--max-border));border-radius:999px;color:var(--max-accent-strong);background:color-mix(in srgb,var(--max-accent) 7%,var(--max-surface));box-shadow:0 2px 8px #3c404314;font:inherit;font-size:13px;font-weight:600;line-height:1;cursor:pointer}.support-ticket-shortcut:hover{border-color:color-mix(in srgb,var(--max-accent) 45%,var(--max-border));background:color-mix(in srgb,var(--max-accent) 11%,var(--max-surface))}.support-ticket-shortcut i{font-size:15px}.assistant-composer{display:flex;width:100%;box-sizing:border-box;gap:8px;align-items:center;margin:0 0 24px;padding:8px 8px 8px 18px;border:1px solid var(--max-border);border-radius:28px;background:var(--max-surface);box-shadow:0 1px 2px #3c404314,0 6px 20px #3c40431a;transition:border-color .16s ease,box-shadow .16s ease}.assistant-composer:focus-within{border-color:color-mix(in srgb,var(--max-accent) 36%,var(--max-border));box-shadow:0 1px 2px #3c404314,0 8px 24px #3c404324}.assistant-composer textarea{flex:1;min-height:44px;height:44px;max-height:132px;box-sizing:border-box;padding:11px 2px;border:0;border-radius:0;outline:0;color:var(--max-text);background:transparent;box-shadow:none;font:inherit;font-size:15px;line-height:22px;resize:none}.assistant-composer textarea::placeholder{color:var(--max-muted);opacity:.84}.assistant-composer textarea:focus{border:0;outline:0;box-shadow:none}.assistant-composer button[type=submit]{width:44px;height:44px;flex:0 0 auto;border-radius:50%;background:var(--max-accent)}.assistant-composer button[type=submit]:disabled{border-color:transparent;color:var(--max-muted);background:transparent;opacity:.5}.support-ticket-overlay{position:absolute;z-index:100;inset:0;display:flex;overflow:auto;align-items:flex-start;justify-content:center;padding:24px;background:#1f1f1f70;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.support-ticket-dialog{position:relative;display:flex;width:min(700px,100%);flex-direction:column;margin:auto 0;border:1px solid var(--max-border);border-radius:22px;color:var(--max-support-text);background:var(--max-surface);box-shadow:0 24px 72px #1f1f1f47}.feedback-dialog{max-height:calc(100% - 48px);overflow:hidden}.feedback-dialog .feedback-form{display:flex;min-height:0;flex:1 1 auto;flex-direction:column;overflow:hidden;padding:0}.feedback-header{position:sticky;z-index:2;top:0;flex:0 0 auto;background:var(--max-surface)}.feedback-header p{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.feedback-form-body{min-height:0;flex:1 1 auto;padding:18px 22px;overflow-y:auto;overscroll-behavior:contain}.feedback-form .support-ticket-fields{gap:12px 18px}.feedback-form .support-ticket-field{gap:5px}.feedback-form .support-ticket-field textarea{min-height:72px}.feedback-actions{position:sticky;z-index:2;bottom:0;flex:0 0 auto;margin:0;padding:14px 22px;border-top:1px solid var(--max-border);background:var(--max-surface)}.support-ticket-header{display:flex;gap:14px;align-items:center;padding:20px 22px;border-bottom:1px solid var(--max-border)}.support-ticket-header-icon{width:44px;height:44px;flex-basis:44px;border-radius:14px;font-size:19px}.support-ticket-header>div{min-width:0;flex:1}.support-ticket-header h2,.support-ticket-header p,.support-ticket-success h3,.support-ticket-success p{margin:0}.support-ticket-header h2{color:var(--max-support-text);font-size:19px;font-weight:600;line-height:1.3}.support-ticket-header p{margin-top:3px;color:var(--max-muted);font-size:13px;line-height:1.4}.support-ticket-close{display:inline-flex;width:38px;height:38px;flex:0 0 38px;align-items:center;justify-content:center;padding:0;appearance:none;border:0;border-radius:50%;color:var(--max-muted);background:transparent;font:inherit;cursor:pointer}.support-ticket-close:hover{color:var(--max-support-text);background:var(--max-surface-soft)}.support-ticket-form{min-height:0;overflow:visible;padding:22px}.support-ticket-fields{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:18px}.support-ticket-field{display:flex;min-width:0;flex-direction:column;gap:7px;color:var(--max-support-text);font-size:13px;font-weight:600}.support-ticket-field>span{display:flex;gap:5px;align-items:baseline}.support-ticket-field>span small{color:var(--max-muted);font-size:11px;font-weight:400}.support-ticket-field-wide{grid-column:1/-1}.support-ticket-field input,.support-ticket-field textarea{width:100%;min-height:44px;padding:10px 12px;border:1px solid var(--max-border);border-radius:10px;outline:0;color:var(--max-support-text);background:var(--max-surface);box-shadow:none;font:inherit;font-size:14px;font-weight:400;line-height:1.45}.support-ticket-field textarea{min-height:116px;resize:vertical}.support-ticket-field input[readonly],.support-ticket-field textarea[readonly]{color:color-mix(in srgb,var(--max-support-text) 82%,var(--max-muted));background:color-mix(in srgb,var(--max-muted) 6%,var(--max-surface));cursor:default}.support-ticket-field input::placeholder,.support-ticket-field textarea::placeholder{color:var(--max-muted);opacity:.82}.support-ticket-field input:focus,.support-ticket-field textarea:focus{border-color:var(--max-accent);box-shadow:0 0 0 3px color-mix(in srgb,var(--max-accent) 13%,transparent)}:host ::ng-deep .support-ticket-dialog .p-select,:host ::ng-deep .support-ticket-dialog .p-multiselect{min-height:44px;border-color:var(--max-border);border-radius:10px;color:var(--max-support-text);background:var(--max-surface);box-shadow:none;font:inherit;font-size:14px;font-weight:400}:host ::ng-deep .support-ticket-dialog .p-select:not(.p-disabled).p-focus,:host ::ng-deep .support-ticket-dialog .p-multiselect:not(.p-disabled).p-focus{border-color:var(--max-accent);box-shadow:0 0 0 3px color-mix(in srgb,var(--max-accent) 13%,transparent)}:host ::ng-deep .support-ticket-dialog .p-select-label,:host ::ng-deep .support-ticket-dialog .p-multiselect-label,:host ::ng-deep .support-ticket-dialog .p-select-dropdown,:host ::ng-deep .support-ticket-dialog .p-multiselect-dropdown{color:var(--max-support-text);font:inherit;font-size:14px}:host ::ng-deep .support-ticket-dialog .p-select-label,:host ::ng-deep .support-ticket-dialog .p-multiselect-label{display:flex;min-height:42px;align-items:center}:host ::ng-deep .support-ticket-dialog .p-multiselect-label{flex-wrap:wrap;gap:5px;padding-block:5px}:host ::ng-deep .support-selected-tags{display:inline-flex;min-width:0;flex-wrap:wrap;gap:5px;align-items:center}:host ::ng-deep .support-ticket-dialog .p-tag{font-size:12px;font-weight:600}:host ::ng-deep .support-ticket-dialog .support-severity-tag,:host ::ng-deep .support-ticket-dialog .support-severity-option{color:#fff;background:var(--support-severity-color)}:host ::ng-deep .support-ticket-dialog .p-tag-icon{font-size:11px}:host ::ng-deep .support-ticket-dialog .p-select-option,:host ::ng-deep .support-ticket-dialog .p-multiselect-option{color:var(--max-support-text)}:host ::ng-deep .support-ticket-dialog .p-select-overlay,:host ::ng-deep .support-ticket-dialog .p-multiselect-overlay{border-color:var(--max-border);border-radius:12px;color:var(--max-support-text);background:var(--max-surface);box-shadow:0 12px 32px #1f1f1f2e;font:inherit}.support-ticket-notice,.support-ticket-error{margin:16px 0 0;padding:10px 12px;border-radius:10px;font-size:13px;line-height:1.45}.support-ticket-notice{color:var(--max-warning);background:color-mix(in srgb,var(--max-warning) 9%,var(--max-surface))}.support-ticket-error{color:var(--max-danger);background:color-mix(in srgb,var(--max-danger) 8%,var(--max-surface))}.support-ticket-actions{display:flex;gap:10px;justify-content:flex-end;margin-top:22px}.support-ticket-success,.support-ticket-error-page{display:flex;min-height:340px;align-items:center;justify-content:center;padding:38px 24px;flex-direction:column;text-align:center}.support-ticket-error-icon{display:inline-flex;width:64px;height:64px;align-items:center;justify-content:center;border-radius:50%;color:var(--max-danger);background:color-mix(in srgb,var(--max-danger) 12%,var(--max-surface))}.support-ticket-error-icon i,.support-ticket-success-icon i{font-size:40px}.support-ticket-error-page h3{margin:18px 0 0;color:var(--max-support-text);font-size:21px}.support-ticket-error-page p{max-width:420px;margin:7px 0 22px;color:var(--max-muted);font-size:14px;line-height:1.5}.support-ticket-success-icon{width:64px;height:64px;flex-basis:64px;border-radius:50%;color:var(--max-success);background:color-mix(in srgb,var(--max-success) 12%,var(--max-surface))}.support-ticket-success>button{margin-top:1rem}.support-ticket-close i{font-size:20px}.support-ticket-success h3{margin-top:18px;color:var(--max-support-text);font-size:21px}.support-ticket-success p{max-width:420px;margin-top:7px;color:var(--max-muted);font-size:14px;line-height:1.5;white-space:pre-line}.support-ticket-reference{display:flex;gap:6px;align-items:center;margin:22px 0;padding:10px 14px;border:1px solid var(--max-border);border-radius:10px;background:var(--max-surface-soft);font-size:13px}.support-ticket-reference span{color:var(--max-muted)}@keyframes max-thinking{0%{opacity:.55;transform:rotate(-8deg) scale(.86)}to{opacity:1;transform:rotate(8deg) scale(1)}}@media (prefers-reduced-motion: reduce){.message.streaming:before{animation:none}.suggestion-chip,.capability-option-card,.support-welcome-card{transition:none}}@media (max-width: 900px){.assistant-messages{padding-top:34px}}@media (max-width: 640px){.assistant-panel{grid-template-rows:64px minmax(0,1fr) auto}.assistant-header{padding:0 14px}.assistant-subtitle{display:none}.assistant-messages{padding:26px 18px 20px}.message.welcome{padding-top:24px}.message.welcome .suggestions,.assistant-cards,.assistant-visualisations,.capability-option-grid{grid-template-columns:1fr}.message.welcome .suggestion-chip{min-height:60px}.message.user{max-width:88%}.assistant-composer{width:100%;margin-bottom:12px}.assistant-footer{width:calc(100% - 24px)}.support-ticket-overlay{align-items:start;padding:10px}.support-ticket-dialog{max-height:none;border-radius:16px}.feedback-dialog{max-height:calc(100% - 20px)}.support-ticket-header{padding:16px}.support-ticket-header p{display:none}.feedback-header p{display:block}.feedback-form-body{padding:14px 16px}.feedback-actions{padding:12px 16px}.support-ticket-form{overflow:visible;padding:16px}.support-ticket-fields{grid-template-columns:1fr;gap:14px}.support-ticket-field-wide{grid-column:auto}.support-ticket-actions{flex-direction:column-reverse}.support-ticket-actions button{width:100%}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i5.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i5.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i5.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i5.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i6.ButtonDirective, selector: "[pButton]", inputs: ["ptButtonDirective", "hostName", "text", "plain", "raised", "size", "outlined", "rounded", "iconPos", "loadingIcon", "fluid", "label", "icon", "loading", "buttonProps", "severity"] }, { kind: "ngmodule", type: MultiSelectModule }, { kind: "component", type: i7.MultiSelect, selector: "p-multiSelect, p-multiselect, p-multi-select", inputs: ["id", "ariaLabel", "styleClass", "panelStyle", "panelStyleClass", "inputId", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "dataKey", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "chipIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "loading", "virtualScrollItemSize", "loadingIcon", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "showClear", "autofocus", "placeholder", "options", "filterValue", "selectAll", "focusOnHover", "filterFields", "selectOnFocus", "autoOptionFocus", "highlightOnSelect", "size", "variant", "fluid", "appendTo"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad", "onRemove", "onSelectAllChange"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i8.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i9.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "ngmodule", type: TextareaModule }, { kind: "directive", type: i10.Textarea, selector: "[pTextarea], [pInputTextarea]", inputs: ["autoResize", "pSize", "variant", "fluid", "invalid"], outputs: ["onResize"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i11.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip"] }, { kind: "component", type: MaxAgentEntityOptionComponent, selector: "max-agent-entity-option", inputs: ["entity", "disabled"], outputs: ["selected"] }, { kind: "component", type: MaxAgentShiftCardComponent, selector: "max-agent-shift-card", inputs: ["shift", "variant"] }, { kind: "pipe", type: i12.DatePipe, name: "date" }, { kind: "pipe", type: MaxAssistantMarkdownPipe, name: "maxAssistantMarkdown" }] });
|
|
1621
1880
|
}
|
|
1622
1881
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: MaxAssistantComponent, decorators: [{
|
|
1623
1882
|
type: Component,
|
|
@@ -1633,7 +1892,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImpo
|
|
|
1633
1892
|
MaxAssistantMarkdownPipe,
|
|
1634
1893
|
MaxAgentEntityOptionComponent,
|
|
1635
1894
|
MaxAgentShiftCardComponent,
|
|
1636
|
-
], encapsulation: ViewEncapsulation.Emulated, template: "<aside\n class=\"assistant-window\"\n [attr.aria-label]=\"uiCopy.title\"\n role=\"region\"\n>\n <section class=\"assistant-panel\">\n <header class=\"assistant-header\">\n <i class=\"max-assistant-sparkles far fa-sparkles\" aria-hidden=\"true\"></i>\n <div class=\"assistant-identity\">\n <div class=\"assistant-name-row\">\n <h2 class=\"assistant-name\">{{ uiCopy.title }}</h2>\n <span class=\"assistant-beta-tag\">Beta</span>\n </div>\n <span class=\"assistant-subtitle\">{{ uiCopy.subtitle }}</span>\n </div>\n <div class=\"assistant-header-actions\">\n <button\n type=\"button\"\n class=\"header-action\"\n [attr.aria-label]=\"uiCopy.clearLabel\"\n [pTooltip]=\"uiCopy.clearTooltip\"\n tooltipPosition=\"bottom\"\n (click)=\"clearChatSession()\"\n >\n <i class=\"header-action-icon pi pi-refresh\" aria-hidden=\"true\"></i>\n </button>\n <button\n type=\"button\"\n class=\"header-action\"\n [attr.aria-label]=\"uiCopy.closeLabel\"\n [pTooltip]=\"uiCopy.closeTooltip\"\n tooltipPosition=\"bottom\"\n (click)=\"requestClose()\"\n >\n <i class=\"header-action-icon pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </header>\n\n <div #messagesViewport class=\"assistant-messages\">\n @for(message of messages(); track message.id) {\n <article\n class=\"message {{ message.role }}\"\n [class.welcome-message]=\"isWelcomeMessage(message)\"\n [class.welcome]=\"isWelcomeState(message)\"\n [class.error]=\"message.isError\"\n [class.streaming]=\"message.isStreaming\"\n [attr.aria-live]=\"message.isStreaming ? 'polite' : null\"\n [attr.aria-busy]=\"message.isStreaming || null\"\n [attr.role]=\"message.isStreaming ? 'status' : null\"\n >\n @if(message.isStreaming) {\n <p class=\"streaming-progress\">{{ message.content }}</p>\n } @else if(message.displayResponse; as responseDetails) {\n @if(responseDetails.markdown || responseDetails.agentInferredResponse || message.content) {\n <div\n class=\"assistant-result assistant-markdown\"\n [innerHTML]=\"(responseDetails.markdown || responseDetails.agentInferredResponse || message.content) | maxAssistantMarkdown\"\n ></div>\n }\n @if(message.cards?.length) {\n <div class=\"assistant-cards\">\n @for(card of message.cards ?? []; track $index) {\n <section class=\"assistant-card\">\n <header>\n <span class=\"assistant-card-title\">{{ card.title }}</span>\n @if(card.subtitle) {\n <span class=\"assistant-card-subtitle\">{{ card.subtitle }}</span>\n }\n </header>\n <div class=\"assistant-card-metrics\">\n @for(metric of card.metrics; track metric.label) {\n <div class=\"assistant-card-metric\" [class.assistant-card-metric-wide]=\"isListMetric(metric)\" [attr.data-tone]=\"metric.tone || 'default'\">\n <span class=\"assistant-card-label\">{{ metric.label }}</span>\n <span class=\"assistant-card-value\">{{ metric.value }}</span>\n </div>\n }\n </div>\n @if(card.footer) {\n <footer>{{ card.footer }}</footer>\n }\n </section>\n }\n </div>\n }\n @if(responseDetails.searchResults?.length) {\n <div class=\"assistant-cards assistant-search-results\" aria-label=\"Search results\">\n @for(result of responseDetails.searchResults ?? []; track $index) {\n <section class=\"assistant-card assistant-search-result\">\n <header>\n <i\n class=\"assistant-search-result-icon\"\n [class]=\"searchResultIcon(result.type)\"\n aria-hidden=\"true\"\n ></i>\n <div class=\"assistant-search-result-copy\">\n <strong>{{ result.title }}</strong>\n <span>{{ result.type }}</span>\n </div>\n </header>\n <div class=\"suggestions\" aria-label=\"Available destinations\">\n @for(action of result.actions; track action.label) {\n <button\n pButton\n type=\"button\"\n size=\"small\"\n severity=\"secondary\"\n class=\"suggestion-chip\"\n [label]=\"action.label\"\n [icon]=\"searchActionIcon(action)\"\n [disabled]=\"isSending()\"\n (click)=\"performHostAction(action.hostAction)\"\n ></button>\n }\n </div>\n </section>\n }\n </div>\n }\n @if(message.pendingAction; as pendingAction) {\n <section class=\"pending-action\" aria-label=\"Cortex action confirmation\">\n <div class=\"pending-action-heading\">\n <strong>Confirmation required</strong>\n <span>{{ pendingAction.method }}</span>\n </div>\n <p>{{ pendingAction.summary }}</p>\n <small>Expires {{ pendingAction.expiresAt | date: 'mediumTime' }}</small>\n @if(message.actionDecision; as actionDecision) {\n <p class=\"action-decision\">\n {{ actionDecision === 'approve' ? 'Approval sent' : 'Rejection sent' }}\n </p>\n } @else {\n <div class=\"pending-action-buttons\">\n <button\n pButton\n type=\"button\"\n size=\"small\"\n severity=\"success\"\n label=\"Approve\"\n [disabled]=\"isSending()\"\n (click)=\"resolvePendingAction(message, 'approve')\"\n ></button>\n <button\n pButton\n type=\"button\"\n size=\"small\"\n outlined\n severity=\"secondary\"\n label=\"Reject\"\n [disabled]=\"isSending()\"\n (click)=\"resolvePendingAction(message, 'reject')\"\n ></button>\n </div>\n }\n </section>\n }\n @if(responseDetails.shiftCardGroups?.length) {\n <div class=\"assistant-shift-groups\" aria-label=\"Team shifts\">\n @for(group of responseDetails.shiftCardGroups ?? []; track group.title) {\n <section class=\"assistant-shift-group\">\n <h3>{{ group.title }}</h3>\n <div class=\"assistant-shift-card-grid\">\n @for(shift of group.shifts; track shift.id || $index) {\n <max-agent-shift-card\n [shift]=\"shift\"\n variant=\"definition\"\n ></max-agent-shift-card>\n }\n </div>\n </section>\n }\n </div>\n }\n @if(responseDetails.rota; as rota) {\n <section class=\"assistant-rota\" [attr.aria-label]=\"rota.title\">\n <div class=\"assistant-rota-heading\">\n <h3>{{ rota.title }}</h3>\n <div class=\"assistant-rota-summary\">\n @if(rota.startDate) {\n <span><small>From</small><strong>{{ rota.startDate }}</strong></span>\n }\n <span><small>Weeks</small><strong>{{ rota.weeksCount }}</strong></span>\n @if(rota.contracted) {\n <span><small>Contracted</small><strong>{{ rota.contracted }}</strong></span>\n }\n @if(rota.autoPublish) {\n <span><small>Auto publish</small><strong>{{ rota.autoPublish }}</strong></span>\n }\n </div>\n </div>\n <div class=\"assistant-rota-scroll\">\n @for(week of rota.weeks; track week.week) {\n <section class=\"assistant-rota-week\">\n <header class=\"assistant-rota-week-heading\">\n <strong>Week {{ week.week }}</strong>\n @if(week.duration) {\n <span>{{ week.duration }}</span>\n }\n </header>\n <div class=\"assistant-rota-week-grid\">\n @for(day of week.days; track day.day) {\n <article class=\"assistant-rota-day\">\n <header>\n <strong>{{ day.label }}</strong>\n @if(day.period) {\n <span>{{ day.period }}</span>\n }\n </header>\n <div class=\"assistant-rota-day-shifts\">\n @for(shift of day.shifts; track shift.id || $index) {\n <max-agent-shift-card\n [shift]=\"shift\"\n variant=\"rota\"\n ></max-agent-shift-card>\n } @empty {\n <span class=\"assistant-rota-empty\">No shifts</span>\n }\n </div>\n </article>\n }\n </div>\n </section>\n } @empty {\n <p class=\"assistant-rota-no-weeks\">No rota weeks were returned.</p>\n }\n </div>\n </section>\n }\n @if(responseDetails.visualisations?.length) {\n <div class=\"assistant-visualisations\">\n @for(visualisation of responseDetails.visualisations ?? []; track visualisation.title) {\n <section class=\"assistant-visualisation\">\n <header class=\"assistant-export-heading\">\n <h3>{{ visualisation.title }}</h3>\n <button\n pButton\n type=\"button\"\n size=\"small\"\n severity=\"secondary\"\n class=\"assistant-export-action assistant-export-action-pdf\"\n icon=\"pi pi-file-pdf\"\n [attr.aria-label]=\"'Export ' + visualisation.title + ' as PDF'\"\n (click)=\"exportVisualisation(visualisation)\"\n ></button>\n </header>\n @if(visualisation.type === 'doughnut') {\n <div class=\"assistant-doughnut-layout\">\n <div\n class=\"assistant-doughnut\"\n role=\"img\"\n [attr.aria-label]=\"chartAriaLabel(visualisation)\"\n >\n <svg viewBox=\"0 0 42 42\" aria-hidden=\"true\" focusable=\"false\">\n <circle\n class=\"assistant-doughnut-track\"\n cx=\"21\"\n cy=\"21\"\n r=\"15.9155\"\n ></circle>\n @for(value of visualisation.values; track $index; let valueIndex = $index) {\n <circle\n class=\"assistant-doughnut-segment\"\n cx=\"21\"\n cy=\"21\"\n r=\"15.9155\"\n pathLength=\"100\"\n [attr.stroke]=\"chartColor(visualisation, valueIndex)\"\n [attr.stroke-dasharray]=\"doughnutDashArray(visualisation, valueIndex)\"\n [attr.stroke-dashoffset]=\"doughnutDashOffset(visualisation, valueIndex)\"\n ></circle>\n }\n </svg>\n <span><strong>{{ chartTotal(visualisation) }}</strong>{{ visualisation.valueLabel || 'people' }}</span>\n </div>\n <div class=\"assistant-chart-legend\">\n @for(label of visualisation.labels; track $index; let labelIndex = $index) {\n <div class=\"assistant-chart-legend-item\">\n <i [style.background]=\"chartColor(visualisation, labelIndex)\"></i>\n <span>{{ label }}</span>\n <strong>{{ visualisation.values[labelIndex] || 0 }}</strong>\n </div>\n }\n </div>\n </div>\n } @else {\n <div\n class=\"assistant-bar-chart\"\n role=\"img\"\n [attr.aria-label]=\"chartAriaLabel(visualisation)\"\n >\n @for(label of visualisation.labels; track $index; let labelIndex = $index) {\n <div class=\"assistant-bar-row\">\n <div class=\"assistant-bar-label\">\n <span>{{ label }}</span>\n <strong>{{ visualisation.values[labelIndex] || 0 }}</strong>\n </div>\n <div class=\"assistant-bar-track\" aria-hidden=\"true\">\n <i\n [style.width.%]=\"barWidth(visualisation, labelIndex)\"\n [style.background]=\"chartColor(visualisation, labelIndex)\"\n ></i>\n </div>\n </div>\n }\n </div>\n }\n </section>\n }\n </div>\n }\n @if(getResponseGrid(responseDetails).length) {\n <div class=\"assistant-tables\">\n @for(table of getResponseGrid(responseDetails); track $index) {\n <section class=\"assistant-table-section\">\n <header class=\"assistant-export-heading\">\n @if(table.title) {\n <h3>{{ table.title }}</h3>\n }\n <button\n pButton\n type=\"button\"\n size=\"small\"\n severity=\"secondary\"\n class=\"assistant-export-action assistant-export-action-excel\"\n icon=\"pi pi-file-excel\"\n [attr.aria-label]=\"'Export ' + (table.title || 'results') + ' to Excel'\"\n (click)=\"exportTable(table)\"\n ></button>\n </header>\n <div class=\"assistant-table-wrap\">\n <table>\n <thead>\n <tr>\n @for(column of table.columns; track column.field) {\n <th>{{ column.header }}</th>\n }\n @if(table.actions?.length) {\n <th>Actions</th>\n }\n </tr>\n </thead>\n <tbody>\n @for(row of table.rows; track $index; let rowIndex = $index) {\n <tr>\n @for(column of table.columns; track column.field) {\n <td>{{ row[column.field] }}</td>\n }\n @if(table.actions?.length) {\n <td>\n <div class=\"assistant-table-actions\">\n @for(action of getTableRowActions(table, rowIndex); track action.label) {\n <button\n pButton\n type=\"button\"\n size=\"small\"\n [severity]=\"action.tone || 'secondary'\"\n [outlined]=\"action.tone === 'danger'\"\n [label]=\"action.label\"\n [disabled]=\"isSending()\"\n (click)=\"useTableAction(action)\"\n ></button>\n }\n </div>\n </td>\n }\n </tr>\n }\n </tbody>\n </table>\n </div>\n </section>\n }\n </div>\n }\n @if(message.sources?.length) {\n <div class=\"assistant-sources\">\n <strong>Sources</strong>\n @for(source of message.sources ?? []; track source.citation) {\n <span>{{ source.citation }}</span>\n }\n </div>\n }\n @if(developerDetailsEnabled && message.developerTrace?.steps?.length) {\n @if(isDetailsVisible(message.id)) {\n <div class=\"details-dialog-backdrop\" (click)=\"toggleDetails(message.id)\">\n <section\n class=\"developer-details\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"Agent processing details\"\n (click)=\"$event.stopPropagation()\"\n >\n <header class=\"developer-details-header\">\n <div>\n <span class=\"developer-eyebrow\">Developer trace</span>\n <h3>How this request was processed</h3>\n <p>A technical, step-by-step account of routing, inference, tools and results.</p>\n </div>\n <div class=\"details-dialog-actions\">\n <button\n type=\"button\"\n class=\"details-dialog-close\"\n aria-label=\"Close processing details\"\n (click)=\"toggleDetails(message.id)\"\n >\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </header>\n\n @if(message.developerTrace!.run; as run) {\n <section class=\"trace-run-summary\" aria-label=\"Run summary\">\n <div class=\"trace-metric\"><span>Total runtime</span><strong>{{ run.durationMs }} ms</strong></div>\n <div class=\"trace-metric\"><span>Model calls</span><strong>{{ run.llmCalls }}</strong></div>\n <div class=\"trace-metric\"><span>Embedding calls</span><strong>{{ run.embeddingCalls }}</strong></div>\n <div class=\"trace-metric\"><span>API calls</span><strong>{{ run.apiCalls }}</strong></div>\n <div class=\"trace-loop-policy\">\n <div>\n <span>Execution architecture</span>\n <strong>Deterministic step pipeline</strong>\n </div>\n <span class=\"trace-no-loop\">No autonomous model loop</span>\n <p>{{ run.loopPolicy }}</p>\n </div>\n </section>\n }\n\n <ol class=\"workflow-trace\">\n @for(step of message.developerTrace!.steps; track step.id; let stepIndex = $index) {\n <li class=\"workflow-step\" [attr.data-status]=\"traceStepTone(step)\">\n <section class=\"workflow-section\">\n <button\n type=\"button\"\n class=\"workflow-step-toggle\"\n [attr.aria-expanded]=\"isTraceStepExpanded(message.id, step.id)\"\n (click)=\"toggleTraceStep(message.id, step.id)\"\n >\n <div>\n <span class=\"workflow-step-number\">Step {{ stepIndex + 1 }}</span>\n <h4>{{ step.title }}</h4>\n <span class=\"workflow-category\">{{ formatTraceCategory(step.category) }}</span>\n </div>\n <div class=\"workflow-meta\">\n <span class=\"workflow-status\">{{ traceStepStatus(step) }}</span>\n @if(step.durationMs !== undefined) {\n <span>{{ step.durationMs }} ms</span>\n }\n <i\n class=\"pi workflow-expand-icon\"\n [class.pi-chevron-down]=\"isTraceStepExpanded(message.id, step.id)\"\n [class.pi-chevron-right]=\"!isTraceStepExpanded(message.id, step.id)\"\n aria-hidden=\"true\"\n ></i>\n </div>\n </button>\n\n @if(isTraceStepExpanded(message.id, step.id)) {\n <div class=\"workflow-step-content\">\n @if(step.metadata?.summary) {\n <p class=\"workflow-summary\">{{ step.metadata!.summary }}</p>\n }\n\n @if(step.metadata?.technology; as technology) {\n <div class=\"trace-technology\">\n <span class=\"trace-section-label\">Technology</span>\n <div class=\"trace-inline-facts\">\n <span><small>Component</small>{{ technology.component }}</span>\n @if(technology.model) { <span><small>Model</small>{{ technology.model }}</span> }\n @if(technology.library) { <span><small>Library</small>{{ technology.library }}</span> }\n @if(technology.provider) { <span><small>Provider</small>{{ technology.provider }}</span> }\n @if(technology.operation) { <span><small>Operation</small>{{ technology.operation }}</span> }\n </div>\n </div>\n }\n\n @if(step.metadata?.control; as control) {\n <div class=\"trace-control\">\n <div>\n <span class=\"trace-section-label\">Stop control</span>\n <strong>{{ formatTraceLabel(control.mode) }}</strong>\n </div>\n @if(control.maximumIterations !== undefined) {\n <span>{{ control.iterationsUsed ?? 0 }} / {{ control.maximumIterations }} iteration</span>\n }\n <p>{{ control.stopCondition }}</p>\n </div>\n }\n\n @switch(step.category) {\n @case('request') {\n @if(traceField(step.input, 'userQuery'); as userQuery) {\n <div class=\"trace-query\">\n <span>Original user query</span>\n <blockquote>{{ formatTraceScalar(userQuery) }}</blockquote>\n </div>\n }\n <div class=\"trace-card-grid\">\n @for(group of [\n { label: 'Product', value: traceMapField(step.input, 'product') },\n { label: 'User', value: traceMapField(step.input, 'user') },\n { label: 'Request context', value: traceMapField(step.input, 'requestContext') },\n { label: 'Conversation', value: traceMapField(step.input, 'conversation') },\n { label: 'Live API context', value: traceMapField(step.input, 'liveApi') }\n ]; track group.label) {\n @if(group.value) {\n <section class=\"trace-data-card\">\n <h5>{{ group.label }}</h5>\n <dl class=\"trace-field-list\">\n @for(entry of traceEntries(group.value, group.label === 'User' ? ['permissions'] : []); track entry.key) {\n <div><dt>{{ entry.label }}</dt><dd>{{ formatTraceScalar(entry.value) }}</dd></div>\n }\n </dl>\n </section>\n }\n }\n </div>\n }\n\n @case('intent_projection') {\n <div class=\"trace-transform\">\n <div>\n <span>Original query</span>\n <p>{{ formatTraceScalar(traceField(step.output, 'originalUserQuery') ?? traceField(step.input, 'originalUserQuery')) }}</p>\n </div>\n <span class=\"trace-transform-arrow\" aria-hidden=\"true\">\u2192</span>\n <div class=\"trace-transform-result\">\n <span>Generalised intent sent to embedding</span>\n <p>{{ formatTraceScalar(traceField(step.output, 'generalisedIntent') ?? traceField(step.output, 'routingText')) }}</p>\n </div>\n </div>\n @if(traceArrayField(step.output, 'removedArguments').length) {\n <div class=\"trace-section\">\n <span class=\"trace-section-label\">Arguments removed before routing</span>\n <div class=\"trace-entity-list\">\n @for(argument of traceArrayField(step.output, 'removedArguments'); track $index) {\n <span><small>{{ formatTraceScalar(traceField(argument, 'kind')) }}</small>{{ formatTraceScalar(traceField(argument, 'value')) }}</span>\n }\n </div>\n </div>\n }\n }\n\n @case('embedding') {\n <div class=\"trace-query trace-query-compact\">\n <span>Embedded text</span>\n <blockquote>{{ formatTraceScalar(traceField(step.input, 'generalisedIntent')) }}</blockquote>\n </div>\n <div class=\"trace-stat-grid\">\n <div><span>Embedding model</span><strong>{{ formatTraceScalar(traceField(step.output, 'model') ?? traceField(step.input, 'model')) }}</strong></div>\n <div><span>Dimensions</span><strong>{{ formatTraceScalar(traceField(step.output, 'dimensions')) }}</strong></div>\n <div><span>Vector magnitude</span><strong>{{ formatTraceScalar(traceField(step.output, 'vectorMagnitude')) }}</strong></div>\n <div><span>Full vector exposed</span><strong>{{ formatTraceScalar(traceField(step.output, 'fullVectorShown')) }}</strong></div>\n </div>\n @if(traceField(step.output, 'vectorPreview'); as vectorPreview) {\n <div class=\"trace-vector\">\n <span>Vector preview</span>\n <code>{{ formatTraceScalar(vectorPreview) }}</code>\n </div>\n }\n }\n\n @case('capability_routing') {\n @if(traceMapField(step.output, 'routing'); as routing) {\n <div class=\"trace-supabase-call\">\n <div><span>Routing strategy</span><strong>{{ formatTraceScalar(traceField(routing, 'strategy')) }}</strong></div>\n <div><span>Cache status</span><strong>{{ formatTraceScalar(traceField(routing, 'cacheStatus')) }}</strong></div>\n <div><span>Supabase RPC executed</span><strong>{{ formatTraceScalar(traceField(routing, 'supabaseRpcExecuted')) }}</strong></div>\n <div><span>Vector search executed</span><strong>{{ formatTraceScalar(traceField(routing, 'vectorSearchExecuted')) }}</strong></div>\n @if(traceField(routing, 'supabaseRpcExecuted')) {\n <div><span>Supabase RPC</span><strong>{{ formatTraceScalar(traceField(routing, 'rpc')) }}</strong></div>\n <div><span>Database</span><strong>{{ formatTraceScalar(traceField(routing, 'database')) }}</strong></div>\n @if(traceArrayField(routing, 'tables').length) {\n <div class=\"trace-table-list\">\n <span>Tables searched</span>\n <div>\n @for(table of traceArrayField(routing, 'tables'); track $index) {\n <code>{{ formatTraceScalar(table) }}</code>\n }\n </div>\n </div>\n }\n }\n </div>\n } @else {\n <div class=\"trace-supabase-call\">\n <div><span>Supabase RPC</span><strong>{{ formatTraceScalar(traceField(step.input, 'rpc')) }}</strong></div>\n <div><span>Database</span><strong>{{ formatTraceScalar(traceField(step.input, 'database')) }}</strong></div>\n @if(traceArrayField(step.input, 'tables').length) {\n <div class=\"trace-table-list\">\n <span>Tables searched</span>\n <div>\n @for(table of traceArrayField(step.input, 'tables'); track $index) {\n <code>{{ formatTraceScalar(table) }}</code>\n }\n </div>\n </div>\n }\n </div>\n }\n @if(traceMapField(step.output, 'decision'); as decision) {\n <section class=\"trace-decision\">\n <span>Routing decision</span>\n <strong>{{ formatTraceScalar(decision['selectedCapabilityLabel'] ?? decision['selectedCapabilityKey']) }}</strong>\n <div>\n <span>Status: {{ formatTraceScalar(decision['status']) }}</span>\n <span>Confidence: {{ formatSimilarity(decision['confidence']) }}</span>\n <span>Runner-up: {{ formatSimilarity(decision['runnerUpConfidence']) }}</span>\n </div>\n </section>\n }\n @if(traceArrayField(step.output, 'matchedCapabilities').length) {\n <div class=\"trace-ranking-wrap\">\n <span class=\"trace-section-label\">Ranked capability matches</span>\n <table class=\"trace-ranking\">\n <thead><tr><th>#</th><th>Capability</th><th>Combined</th><th>Semantic</th><th>Definition</th><th>Example</th><th>Keyword</th></tr></thead>\n <tbody>\n @for(candidate of traceArrayField(step.output, 'matchedCapabilities'); track $index) {\n <tr>\n <td>{{ formatTraceScalar(traceField(candidate, 'rank')) }}</td>\n <td><strong>{{ formatTraceScalar(traceField(candidate, 'label')) }}</strong><code>{{ formatTraceScalar(traceField(candidate, 'capabilityKey')) }}</code></td>\n <td>{{ formatSimilarity(traceField(candidate, 'combinedScore')) }}</td>\n <td>{{ formatSimilarity(traceField(candidate, 'semanticScore')) }}</td>\n <td>{{ formatSimilarity(traceField(candidate, 'definitionScore')) }}</td>\n <td>{{ formatSimilarity(traceField(candidate, 'exampleScore')) }}</td>\n <td>{{ formatSimilarity(traceField(candidate, 'keywordScore')) }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n }\n\n @case('argument_extraction') {\n <div class=\"trace-card-grid\">\n @if(traceMapField(step.output, 'selectedCapability') ?? traceMapField(step.input, 'selectedCapability'); as capability) {\n <section class=\"trace-data-card trace-data-card-accent\">\n <h5>Selected capability</h5>\n <dl class=\"trace-field-list\">\n @for(entry of traceEntries(capability); track entry.key) {\n <div><dt>{{ entry.label }}</dt><dd>{{ formatTraceScalar(entry.value) }}</dd></div>\n }\n </dl>\n </section>\n }\n @if(traceMapField(step.input, 'tool'); as tool) {\n <section class=\"trace-data-card\">\n <h5>Allowlisted tool</h5>\n <dl class=\"trace-field-list\">\n @for(entry of traceEntries(tool); track entry.key) {\n <div><dt>{{ entry.label }}</dt><dd>{{ formatTraceScalar(entry.value) }}</dd></div>\n }\n </dl>\n </section>\n }\n </div>\n @if(traceMapField(step.output, 'extractedArguments'); as arguments) {\n <section class=\"trace-arguments\">\n <span class=\"trace-section-label\">Arguments extracted from the original query</span>\n <dl class=\"trace-argument-grid\">\n @for(entry of traceEntries(arguments); track entry.key) {\n <div><dt>{{ entry.label }}</dt><dd>{{ formatTraceScalar(entry.value) }}</dd></div>\n }\n </dl>\n </section>\n }\n @if(traceMapField(step.output, 'plannedToolCall'); as plannedCall) {\n <div class=\"trace-tool-call\">\n <span>Planned tool call</span>\n <strong>{{ formatTraceScalar(plannedCall['method']) }} \u00B7 {{ formatTraceScalar(plannedCall['toolName']) }}</strong>\n <pre>{{ formatTraceValue(plannedCall['arguments']) }}</pre>\n </div>\n }\n }\n\n @case('api_call') {\n @if(traceField(step.input, 'sql'); as sql) {\n <div class=\"trace-tool-call trace-sql-query\">\n <span>SQL sent to MySQL MCP</span>\n <strong>{{ formatTraceScalar(traceField(step.input, 'toolName')) }}</strong>\n <pre>{{ formatTraceScalar(sql) }}</pre>\n </div>\n }\n @if(traceField(step.input, 'method') || traceField(step.input, 'path')) {\n <div class=\"trace-api-route\">\n <span class=\"trace-http-method\">{{ formatTraceScalar(traceField(step.input, 'method')) }}</span>\n <code>{{ formatTraceScalar(traceField(step.input, 'path')) }}</code>\n @if(getHttpStatus(step); as statusCode) {\n <span class=\"trace-http-status\" [class.success]=\"isHttpSuccessful(step)\" [class.error]=\"!isHttpSuccessful(step)\">\n HTTP {{ statusCode }} \u00B7 {{ isHttpSuccessful(step) ? 'Success' : 'Error' }}\n </span>\n }\n </div>\n }\n <div class=\"trace-payload-grid\">\n @if(traceField(step.input, 'body'); as requestBody) {\n <section><span>Request payload</span><pre>{{ formatTraceValue(requestBody) }}</pre></section>\n }\n @if(traceField(step.output, 'response'); as apiResponse) {\n <section><span>API response</span><pre>{{ formatTraceValue(apiResponse) }}</pre></section>\n }\n @if(traceField(step.input, 'sql') && step.output !== undefined) {\n <section><span>MySQL MCP execution details</span><pre>{{ formatTraceValue(step.output) }}</pre></section>\n }\n </div>\n }\n\n @case('action') {\n <div class=\"trace-card-grid\">\n <section class=\"trace-data-card\">\n <h5>Workflow input</h5>\n <dl class=\"trace-field-list\">\n @for(entry of traceEntries(step.input); track entry.key) {\n <div><dt>{{ entry.label }}</dt><dd>{{ formatTraceScalar(entry.value) }}</dd></div>\n }\n </dl>\n </section>\n <section class=\"trace-data-card trace-data-card-accent\">\n <h5>Outcome</h5>\n <dl class=\"trace-field-list\">\n @for(entry of traceEntries(step.output); track entry.key) {\n <div><dt>{{ entry.label }}</dt><dd>{{ formatTraceScalar(entry.value) }}</dd></div>\n }\n </dl>\n </section>\n </div>\n }\n\n @case('response') {\n @if(traceField(step.output, 'answer'); as answer) {\n <div class=\"trace-query\"><span>Final grounded response</span><blockquote>{{ formatTraceScalar(answer) }}</blockquote></div>\n }\n <dl class=\"trace-argument-grid\">\n @for(entry of traceEntries(step.output); track entry.key) {\n @if(entry.key !== 'answer') {\n <div><dt>{{ entry.label }}</dt><dd>{{ formatTraceScalar(entry.value) }}</dd></div>\n }\n }\n </dl>\n }\n\n @default {\n <div class=\"trace-payload-grid\">\n @if(step.input !== undefined) {\n <section><span>Input</span><pre>{{ formatTraceValue(step.input) }}</pre></section>\n }\n @if(step.output !== undefined) {\n <section><span>Output</span><pre>{{ formatTraceValue(step.output) }}</pre></section>\n }\n </div>\n }\n }\n\n @if(step.error; as error) {\n <div class=\"trace-error\" [class.trace-warning]=\"step.category === 'api_call' && isHttpSuccessful(step)\">\n <strong class=\"trace-error-heading\">\n @if(step.category === 'api_call' && isHttpSuccessful(step)) {\n Post-response processing stopped\n } @else {\n Step stopped@if(error.statusCode) { \u00B7 HTTP {{ error.statusCode }} }\n }\n </strong>\n <strong class=\"trace-error-legacy\" aria-hidden=\"true\">\n Failed@if(error.statusCode) { \u2014 HTTP {{ error.statusCode }} }\n </strong>\n <span>{{ error.message }}</span>\n </div>\n }\n </div>\n }\n </section>\n </li>\n }\n </ol>\n </section>\n </div>\n }\n }\n } @else {\n @if(message.role === 'assistant') {\n <div\n class=\"assistant-markdown\"\n [innerHTML]=\"message.content | maxAssistantMarkdown\"\n ></div>\n @if(isWelcomeState(message) && bootstrapConfig.initialDescription; as initialDescription) {\n <p class=\"welcome-description\">{{ initialDescription }}</p>\n }\n @if(isWelcomeState(message)) {\n <button\n type=\"button\"\n class=\"support-welcome-card\"\n aria-label=\"Raise a support ticket\"\n (click)=\"openSupportTicket()\"\n >\n <span class=\"support-welcome-icon\" aria-hidden=\"true\">\n <i class=\"far fa-user-headset\"></i>\n </span>\n <span class=\"support-welcome-copy\">\n <strong>Raise a support ticket</strong>\n <small>Send details directly to our support team.</small>\n </span>\n <i class=\"support-welcome-arrow pi pi-arrow-right\" aria-hidden=\"true\"></i>\n </button>\n }\n } @else {\n <p>{{ message.content }}</p>\n }\n }\n @if(message.role === 'assistant' && message.suggestions?.length) {\n @if(hasCapabilitySuggestions(message.suggestions)) {\n <div class=\"capability-options\" aria-label=\"Available Maxtime capabilities\">\n @for(group of capabilitySuggestionGroups(message.suggestions); track group.section) {\n <section class=\"capability-option-section\">\n <h3>{{ group.section }}</h3>\n <div class=\"capability-option-grid\">\n @for(suggestion of group.options; track suggestion.structuredAction?.capabilityKey ?? suggestion.label; let optionIndex = $index) {\n <button\n pButton\n type=\"button\"\n severity=\"secondary\"\n class=\"capability-option-card\"\n [disabled]=\"isSending()\"\n [attr.aria-label]=\"'Choose capability: ' + suggestion.label\"\n (click)=\"useSuggestion(suggestion)\"\n >\n <span class=\"capability-option-number\" aria-hidden=\"true\">\n {{ optionIndex + 1 }}\n </span>\n <span class=\"capability-option-copy\">{{ suggestion.label }}</span>\n <i class=\"pi pi-arrow-right capability-option-arrow\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n </section>\n }\n </div>\n } @else if(hasOptionCardSuggestions(message.suggestions, message.status)) {\n <div class=\"clarification-options\" aria-label=\"Clarification options\">\n <div class=\"capability-option-grid clarification-option-grid\">\n @for(suggestion of optionCardSuggestions(message.suggestions, message.status); track suggestionLabel(suggestion); let optionIndex = $index) {\n <button\n pButton\n type=\"button\"\n severity=\"secondary\"\n class=\"capability-option-card clarification-option-card\"\n [disabled]=\"isSending()\"\n [attr.aria-label]=\"'Choose option: ' + suggestionLabel(suggestion)\"\n (click)=\"useSuggestion(suggestion)\"\n >\n <span class=\"capability-option-number\" aria-hidden=\"true\">\n {{ optionIndex + 1 }}\n </span>\n <span class=\"capability-option-copy\">{{ suggestionLabel(suggestion) }}</span>\n <i class=\"pi pi-arrow-right capability-option-arrow\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n </div>\n } @else if(hasEntitySuggestions(message.suggestions)) {\n <div class=\"entity-options\" aria-label=\"Matching options\">\n @for(suggestion of entitySuggestionOptions(message.suggestions); track suggestion.entity.id ?? suggestion.label) {\n <max-agent-entity-option\n [entity]=\"suggestion.entity\"\n [disabled]=\"isSending()\"\n (selected)=\"useSuggestion(suggestion)\"\n ></max-agent-entity-option>\n }\n </div>\n } @else {\n <div class=\"suggestions\">\n @for(suggestion of message.suggestions ?? []; track suggestion) {\n <button\n pButton\n type=\"button\"\n size=\"small\"\n text\n severity=\"secondary\"\n class=\"suggestion-chip\"\n [label]=\"suggestionLabel(suggestion)\"\n (click)=\"useSuggestion(suggestion)\"\n ></button>\n }\n </div>\n }\n }\n @if(message.role === 'assistant' && !isWelcomeMessage(message) && !message.isStreaming) {\n <div class=\"response-actions\">\n <button\n type=\"button\"\n class=\"response-feedback-action\"\n [attr.aria-label]=\"uiCopy.feedbackLabel\"\n [pTooltip]=\"uiCopy.feedbackTooltip\"\n tooltipPosition=\"bottom\"\n (click)=\"openFeedback(message)\"\n >\n <i class=\"pi pi-comment\" aria-hidden=\"true\"></i>\n </button>\n @if(developerDetailsEnabled && message.developerTrace?.steps?.length) {\n <button\n type=\"button\"\n class=\"details-toggle\"\n [attr.aria-expanded]=\"isDetailsVisible(message.id)\"\n (click)=\"toggleDetails(message.id, message.developerTrace!.steps[0]?.id)\"\n >\n {{ isDetailsVisible(message.id) ? 'Hide Developer Trace' : 'Show Developer Trace' }}\n </button>\n }\n </div>\n }\n </article>\n }\n </div>\n\n <footer class=\"assistant-footer\">\n @if(hasConversationStarted()) {\n <button\n type=\"button\"\n class=\"support-ticket-shortcut\"\n aria-label=\"Raise a support ticket\"\n (click)=\"openSupportTicket()\"\n >\n <i class=\"far fa-user-headset\" aria-hidden=\"true\"></i>\n <span>Raise a support ticket</span>\n </button>\n }\n <form class=\"assistant-composer\" (ngSubmit)=\"sendMessage()\">\n <textarea\n #composerInput\n pTextarea\n name=\"assistantPrompt\"\n rows=\"1\"\n [placeholder]=\"uiCopy.placeholder\"\n [ngModel]=\"input()\"\n (ngModelChange)=\"input.set($event)\"\n (keydown)=\"onComposerKeydown($event)\"\n >\n </textarea>\n <button\n pButton\n type=\"submit\"\n icon=\"pi pi-send\"\n aria-label=\"Send message\"\n [disabled]=\"!input().trim() || isSending()\"\n ></button>\n </form>\n </footer>\n </section>\n\n @if(supportTicketVisible()) {\n <section class=\"support-ticket-overlay\" aria-label=\"Support ticket form\">\n <div\n class=\"support-ticket-dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"supportTicketTitle\"\n >\n <header class=\"support-ticket-header\">\n <span class=\"support-ticket-header-icon\" aria-hidden=\"true\">\n <i class=\"far fa-user-headset\"></i>\n </span>\n <div>\n <h2 id=\"supportTicketTitle\">Raise a support ticket</h2>\n <p>Share the details and our support team will take it from here.</p>\n </div>\n <button\n type=\"button\"\n class=\"support-ticket-close\"\n aria-label=\"Close support ticket form\"\n (click)=\"closeSupportTicket()\"\n >\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </header>\n\n @if(supportTicketResult(); as result) {\n <div class=\"support-ticket-success\" role=\"status\">\n <span class=\"support-ticket-success-icon\" aria-hidden=\"true\">\n <i class=\"pi pi-check\"></i>\n </span>\n <h3>Ticket raised</h3>\n <p>{{ result.message }}</p>\n <div class=\"support-ticket-reference\">\n <span>Reference</span>\n <strong>{{ result.ticketReference }}</strong>\n </div>\n <button\n pButton\n type=\"button\"\n label=\"Done\"\n icon=\"pi pi-check\"\n (click)=\"closeSupportTicket()\"\n ></button>\n </div>\n } @else {\n <form class=\"support-ticket-form\" (ngSubmit)=\"submitSupportTicket()\">\n <div class=\"support-ticket-fields\">\n <label class=\"support-ticket-field\">\n <span>Name</span>\n <input\n type=\"text\"\n name=\"supportName\"\n autocomplete=\"name\"\n [value]=\"supportTicketForm.name\"\n readonly\n />\n </label>\n\n <label class=\"support-ticket-field\">\n <span>Email</span>\n <input\n type=\"email\"\n name=\"supportEmail\"\n autocomplete=\"email\"\n [value]=\"supportTicketForm.email\"\n readonly\n />\n </label>\n\n <label class=\"support-ticket-field support-ticket-field-wide\">\n <span>Phone <small>Optional</small></span>\n <input\n type=\"tel\"\n name=\"supportPhone\"\n autocomplete=\"tel\"\n placeholder=\"Add a contact number\"\n [(ngModel)]=\"supportTicketForm.phone\"\n />\n </label>\n\n <label class=\"support-ticket-field\">\n <span>Severity</span>\n <p-select\n inputId=\"supportSeverity\"\n name=\"supportSeverity\"\n [options]=\"supportSeverityOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [fluid]=\"true\"\n [(ngModel)]=\"supportTicketForm.severity\"\n >\n <ng-template #selectedItem let-severity>\n <p-tag\n class=\"support-severity-tag\"\n [value]=\"severity.label\"\n [severity]=\"severity.severity\"\n [rounded]=\"true\"\n ></p-tag>\n </ng-template>\n <ng-template #item let-severity>\n <p-tag\n class=\"support-severity-option\"\n [value]=\"severity.label\"\n [severity]=\"severity.severity\"\n [rounded]=\"true\"\n ></p-tag>\n </ng-template>\n </p-select>\n </label>\n\n <label class=\"support-ticket-field\">\n <span>Tags</span>\n <p-multiselect\n inputId=\"supportTags\"\n name=\"supportTags\"\n placeholder=\"Select relevant areas\"\n [options]=\"supportTags()\"\n optionLabel=\"label\"\n optionValue=\"value\"\n display=\"chip\"\n [filter]=\"true\"\n filterBy=\"label\"\n [showToggleAll]=\"false\"\n [loading]=\"supportTagsLoading()\"\n [fluid]=\"true\"\n [(ngModel)]=\"supportTicketForm.tags\"\n >\n <ng-template #selecteditems let-selectedTags>\n <span class=\"support-selected-tags\">\n @for(tag of selectedTags; track tag.value) {\n <p-tag\n class=\"support-selected-tag\"\n [value]=\"tag.label\"\n [icon]=\"tag.icon\"\n [severity]=\"tag.severity\"\n [rounded]=\"true\"\n ></p-tag>\n }\n </span>\n </ng-template>\n <ng-template #item let-tag>\n <p-tag\n class=\"support-tag-option\"\n [value]=\"tag.label\"\n [icon]=\"tag.icon\"\n [severity]=\"tag.severity\"\n [rounded]=\"true\"\n ></p-tag>\n </ng-template>\n </p-multiselect>\n </label>\n\n <label class=\"support-ticket-field support-ticket-field-wide\">\n <span>Subject</span>\n <input\n type=\"text\"\n name=\"supportSubject\"\n maxlength=\"200\"\n placeholder=\"Summarise the issue\"\n required\n [(ngModel)]=\"supportTicketForm.subject\"\n />\n </label>\n\n <label class=\"support-ticket-field support-ticket-field-wide\">\n <span>How can we help?</span>\n <textarea\n #supportQueryInput\n pTextarea\n name=\"supportQuery\"\n rows=\"5\"\n placeholder=\"Describe the issue, what you expected, and anything you've already tried.\"\n required\n [(ngModel)]=\"supportTicketForm.query\"\n ></textarea>\n </label>\n </div>\n\n @if(!supportTicketForm.name || !supportTicketForm.email) {\n <p class=\"support-ticket-notice\" role=\"alert\">\n Your signed-in name and email are required. Please refresh your Nemesys session and try again.\n </p>\n }\n @if(supportTicketError(); as supportError) {\n <p class=\"support-ticket-error\" role=\"alert\">{{ supportError }}</p>\n }\n\n <div class=\"support-ticket-actions\">\n <button\n pButton\n type=\"button\"\n label=\"Cancel\"\n severity=\"secondary\"\n outlined\n (click)=\"closeSupportTicket()\"\n ></button>\n <button\n pButton\n type=\"submit\"\n label=\"Submit ticket\"\n icon=\"pi pi-send\"\n [loading]=\"supportTicketSubmitting()\"\n [disabled]=\"!canSubmitSupportTicket()\"\n ></button>\n </div>\n </form>\n }\n </div>\n </section>\n }\n\n @if(feedbackVisible()) {\n <section\n class=\"support-ticket-overlay feedback-overlay\"\n aria-label=\"Feedback form\"\n >\n <div\n class=\"support-ticket-dialog feedback-dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"feedbackTitle\"\n >\n <header class=\"support-ticket-header feedback-header\">\n <span class=\"support-ticket-header-icon\" aria-hidden=\"true\">\n <i class=\"pi pi-comment\"></i>\n </span>\n <div>\n <h2 id=\"feedbackTitle\">Help Max improve</h2>\n <p>Tell us what Max could do better.</p>\n </div>\n <button\n type=\"button\"\n class=\"support-ticket-close feedback-close\"\n aria-label=\"Close feedback form\"\n (click)=\"closeFeedback()\"\n >\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </header>\n\n @if(feedbackResult(); as result) {\n <div class=\"support-ticket-success feedback-success\" role=\"status\">\n <span class=\"support-ticket-success-icon\" aria-hidden=\"true\">\n <i class=\"pi pi-check\"></i>\n </span>\n <h3>Feedback received</h3>\n <p>{{ result.message }}</p>\n <div class=\"support-ticket-reference\">\n <span>Reference</span>\n <strong>{{ result.feedbackReference }}</strong>\n </div>\n <button\n pButton\n type=\"button\"\n label=\"Done\"\n icon=\"pi pi-check\"\n (click)=\"closeFeedback()\"\n ></button>\n </div>\n } @else {\n <form class=\"support-ticket-form feedback-form\" (ngSubmit)=\"submitFeedback()\">\n <div class=\"feedback-form-body\">\n <div class=\"support-ticket-fields\">\n <label class=\"support-ticket-field\">\n <span>Name</span>\n <input\n type=\"text\"\n name=\"feedbackName\"\n autocomplete=\"name\"\n [value]=\"feedbackForm.name\"\n readonly\n />\n </label>\n\n <label class=\"support-ticket-field\">\n <span>Email</span>\n <input\n type=\"email\"\n name=\"feedbackEmail\"\n autocomplete=\"email\"\n [value]=\"feedbackForm.email\"\n readonly\n />\n </label>\n\n <label class=\"support-ticket-field\">\n <span>Phone <small>Optional</small></span>\n <input\n type=\"tel\"\n name=\"feedbackPhone\"\n autocomplete=\"tel\"\n placeholder=\"Add a contact number\"\n [(ngModel)]=\"feedbackForm.phone\"\n />\n </label>\n\n <label class=\"support-ticket-field\">\n <span>Feedback type</span>\n <p-select\n inputId=\"feedbackCategory\"\n name=\"feedbackCategory\"\n [options]=\"feedbackCategoryOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [fluid]=\"true\"\n [(ngModel)]=\"feedbackForm.category\"\n ></p-select>\n </label>\n\n <label class=\"support-ticket-field support-ticket-field-wide\">\n <span>Your query</span>\n <textarea\n pTextarea\n name=\"feedbackQuery\"\n rows=\"2\"\n placeholder=\"Enter the question or request you gave Max.\"\n readonly\n required\n [(ngModel)]=\"feedbackForm.query\"\n ></textarea>\n </label>\n\n <label class=\"support-ticket-field support-ticket-field-wide\">\n <span>Assistant response <small>Added automatically when available</small></span>\n <textarea\n pTextarea\n name=\"feedbackAssistantResponse\"\n rows=\"3\"\n placeholder=\"No assistant response is available yet.\"\n [value]=\"feedbackForm.assistantResponse\"\n readonly\n ></textarea>\n </label>\n\n <label class=\"support-ticket-field support-ticket-field-wide\">\n <span>What could be improved?</span>\n <textarea\n #feedbackInput\n pTextarea\n name=\"feedbackDetails\"\n rows=\"3\"\n placeholder=\"Tell us what you expected, what was missing, or how the response could be more useful.\"\n required\n [(ngModel)]=\"feedbackForm.feedback\"\n ></textarea>\n </label>\n </div>\n\n @if(!feedbackForm.name || !feedbackForm.email) {\n <p class=\"support-ticket-notice\" role=\"alert\">\n Your signed-in name and email are required. Please refresh your Nemesys session and try again.\n </p>\n }\n @if(feedbackError(); as error) {\n <p class=\"support-ticket-error\" role=\"alert\">{{ error }}</p>\n }\n </div>\n\n <footer class=\"support-ticket-actions feedback-actions\">\n <button\n pButton\n type=\"button\"\n label=\"Cancel\"\n severity=\"secondary\"\n outlined\n (click)=\"closeFeedback()\"\n ></button>\n <button\n pButton\n type=\"submit\"\n label=\"Send feedback\"\n icon=\"pi pi-send\"\n [loading]=\"feedbackSubmitting()\"\n [disabled]=\"!canSubmitFeedback()\"\n ></button>\n </footer>\n </form>\n }\n </div>\n </section>\n }\n</aside>\n", styles: [":host{position:relative;display:block;width:100%;height:100%;min-height:0}.assistant-launcher{position:relative;width:64px!important;height:64px!important;min-height:64px!important;padding:7px;border:1px solid rgba(124,58,237,.24)!important;border-radius:22px!important;color:inherit!important;background:radial-gradient(circle at 28% 16%,rgba(255,255,255,.98),transparent 38%),linear-gradient(145deg,#fff7ed,#f5f3ff 52%,#fdf2f8)!important;box-shadow:0 0 0 1px #ffffffd9 inset,0 12px 30px #5b21b62e!important;overflow:visible;transition:border-color .22s ease,box-shadow .22s ease,transform .22s cubic-bezier(.2,.8,.2,1);z-index:2}.assistant-launcher:before,.assistant-launcher:after{content:\"\";position:absolute;top:50%;left:50%;width:22px;height:2px;border-radius:999px;background:#0f6cae;opacity:0;transform:translate(-50%,-50%) scale(.6) rotate(0);transition:opacity .18s ease,transform .22s ease;z-index:1}.assistant-launcher:before{transform:translate(-50%,-50%) scale(.6) rotate(45deg)}.assistant-launcher:after{transform:translate(-50%,-50%) scale(.6) rotate(-45deg)}.assistant-launcher:hover,.assistant-launcher:focus-visible{border-color:#ec489975!important;background:radial-gradient(circle at 30% 18%,#fff,transparent 38%),linear-gradient(145deg,#ffedd5,#ede9fe,#fce7f3)!important;box-shadow:0 0 0 3px #a855f71a,0 16px 34px #6d28d938!important;transform:translateY(-2px)}.assistant-launcher.is-open{background:#fff!important;box-shadow:0 0 0 2px #0078c838,0 14px 32px #0f172a2e!important;transform:translateY(0)}.assistant-launcher.is-open:before,.assistant-launcher.is-open:after{opacity:1}.assistant-launcher.is-open:before{transform:translate(-50%,-50%) scale(1) rotate(45deg)}.assistant-launcher.is-open:after{transform:translate(-50%,-50%) scale(1) rotate(-45deg)}.mascot{position:relative;display:inline-grid;width:54px;height:54px;place-items:center;transform-origin:50% 72%;transition:opacity .18s ease,transform .24s ease,filter .24s ease;z-index:0}.mascot-aura{position:absolute;inset:5px;border-radius:50%;background:conic-gradient(from 25deg,#f472b66b,#fbbf2452,#2dd4bf57,#8b5cf66b,#f472b66b);filter:blur(7px);animation:mascot-aura 3s ease-in-out infinite}.mascot-art{position:relative;width:100%;height:100%;overflow:visible;filter:drop-shadow(0 5px 5px rgba(2,75,116,.2));animation:mascot-idle 3.4s ease-in-out infinite}.mascot-shell{fill:#7c3aed}.mascot-ear-left{fill:#ec4899}.mascot-ear-right{fill:#f97316}.mascot-ear{transform-box:fill-box;transform-origin:center}.mascot-face{fill:#211747;stroke:#ffffff4d;stroke-width:1}.mascot-signal{fill:#facc15;stroke:#fff;stroke-width:1.5;transform-box:fill-box;transform-origin:center;animation:mascot-signal 2.2s ease-out infinite}.mascot-antenna,.mascot-sparkle,.mascot-shell-shine,.mascot-smile,.mascot-mark{fill:none;stroke-linecap:round;stroke-linejoin:round}.mascot-antenna{stroke:#6d28d9;stroke-width:2.5}.mascot-sparkle{stroke:#ec4899;stroke-width:2;transform-box:fill-box;transform-origin:center;animation:mascot-sparkle 3.4s ease-in-out infinite}.mascot-shell-shine{stroke:#e9d5ffd1;stroke-width:2}.mascot-eye{fill:#5eead4;transform-box:fill-box;transform-origin:center;animation:mascot-blink 5.2s ease-in-out infinite}.mascot-smile{stroke:#fbbf24;stroke-width:2}.mascot-mark{stroke:#ffffffd1;stroke-width:2.2}.assistant-launcher:hover .mascot-art,.assistant-launcher:focus-visible .mascot-art{animation:mascot-greet .7s cubic-bezier(.2,.8,.2,1)}.assistant-launcher:hover .mascot-ear-right,.assistant-launcher:focus-visible .mascot-ear-right{animation:mascot-ear-wave .7s ease-in-out}.assistant-launcher.is-open .mascot{filter:saturate(1.08);opacity:.24;transform:scale(.82) rotate(-5deg)}.mascot.large{width:52px;height:52px;flex:0 0 auto}@keyframes mascot-idle{0%,to{transform:translateY(0) rotate(0)}50%{transform:translateY(-2px) rotate(1deg)}}@keyframes mascot-greet{0%,to{transform:translateY(0) rotate(0)}35%{transform:translateY(-4px) rotate(-5deg)}65%{transform:translateY(-2px) rotate(4deg)}}@keyframes mascot-ear-wave{0%,to{transform:rotate(0) scaleY(1)}50%{transform:rotate(-12deg) scaleY(1.12)}}@keyframes mascot-blink{0%,45%,49%,to{transform:scaleY(1)}47%{transform:scaleY(.12)}}@keyframes mascot-signal{0%,55%,to{opacity:1;transform:scale(1)}70%{opacity:.55;transform:scale(1.42)}}@keyframes mascot-sparkle{0%,62%,to{opacity:0;transform:scale(.5) rotate(0)}72%{opacity:1;transform:scale(1) rotate(90deg)}84%{opacity:0;transform:scale(.7) rotate(150deg)}}@keyframes mascot-aura{0%,to{opacity:.45;transform:scale(.88)}50%{opacity:.85;transform:scale(1.08)}}.assistant-window{position:relative;width:100%;height:100%;min-height:0;border:1px solid rgba(148,163,184,.24);border-radius:24px;background:#fffffff5;box-shadow:0 24px 70px #0f172a33,0 0 0 1px #ffffffad inset;overflow:hidden;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.assistant-panel{display:grid;grid-template-rows:auto 1fr auto;height:100%;min-height:0;border-radius:inherit;background:linear-gradient(180deg,#f8fafcd1,#f1f5f9f5),var(--max-canvas, #f8fafc);overflow:hidden}.assistant-header,.assistant-composer{display:flex;gap:12px;align-items:center;padding:16px 18px;background:#ffffffeb;border-bottom:1px solid rgba(226,232,240,.86)}.assistant-identity{display:grid;gap:5px;min-width:0}.assistant-name{margin:0;width:fit-content;color:var(--max-accent, #2563eb);font:inherit;font-weight:600}.assistant-subtitle{color:#64748b;font-size:10px;font-weight:600;letter-spacing:.1em;line-height:1.2;text-transform:uppercase}.sources span{color:#64748b;font-size:12px;font-weight:600}.assistant-header .header-action:first-of-type{margin-left:auto}.assistant-header .header-action{width:38px;height:38px;margin-left:0;color:#475569;background:transparent}.assistant-header .header-action:hover{background:#0f172a0f}.assistant-messages{min-height:0;overflow:auto;padding:18px;scrollbar-width:thin}.assistant-messages,.assistant-table-wrap,.assistant-rota-scroll{scrollbar-color:#cbd5e1 transparent;scrollbar-width:thin}.assistant-messages::-webkit-scrollbar,.assistant-table-wrap::-webkit-scrollbar,.assistant-rota-scroll::-webkit-scrollbar{width:6px;height:6px}.assistant-messages::-webkit-scrollbar-track,.assistant-table-wrap::-webkit-scrollbar-track,.assistant-rota-scroll::-webkit-scrollbar-track{background:transparent}.assistant-messages::-webkit-scrollbar-thumb,.assistant-table-wrap::-webkit-scrollbar-thumb,.assistant-rota-scroll::-webkit-scrollbar-thumb{border-radius:999px;background:#cbd5e1}.message{position:relative;width:fit-content;max-width:92%;margin-bottom:14px;padding:12px;border:1px solid var(--border-color, #e2e8f0);border-radius:16px;background:#fff;box-shadow:0 1px 2px #0f172a14,0 10px 24px #0f172a0f;-webkit-user-select:text;user-select:text}.message.assistant{width:100%;max-width:100%}.message.user{width:fit-content;max-width:88%;margin-left:auto;color:#fff;background:var(--primary-color, #2563eb);border-color:var(--border-color, #e2e8f0);border-bottom-right-radius:6px}.message.user p{color:inherit}.message.error{border-color:var(--danger-color, #dc2626)}.message.streaming{padding:0;border:0;color:var(--text-color-secondary, #64748b);background:transparent;box-shadow:none;font-style:italic}.streaming-progress{background:linear-gradient(100deg,var(--max-muted, #64748b) 20%,var(--primary-color, #2563eb) 42%,#a855f7 50%,var(--primary-color, #2563eb) 58%,var(--max-muted, #64748b) 80%);background-size:220% 100%;background-clip:text;-webkit-background-clip:text;-webkit-text-fill-color:transparent;white-space:pre-line;animation:assistant-progress-shimmer 2.2s ease-in-out infinite}@keyframes assistant-progress-shimmer{0%{background-position:120% 0}to{background-position:-20% 0}}.message p{margin:0;line-height:1.45}.assistant-result{color:#1e293b}.assistant-cards{display:grid;gap:10px;margin-top:12px}.assistant-card{overflow:hidden;border:1px solid #e2e8f0;border-radius:12px;background:#fff;box-shadow:0 3px 12px #0f172a0d;font-weight:400}.assistant-card>header{display:grid;gap:3px;padding:13px 16px;border-bottom:1px solid #e2e8f0}.assistant-card-title{color:#0f172a;font-size:14px;font-weight:600}.assistant-card-subtitle,.assistant-card>footer{color:#64748b;font-size:12px}.assistant-card-metrics{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));padding:16px}.assistant-card-metric{display:grid;min-width:0;align-content:start;gap:5px}.assistant-card-metric-wide{grid-column:1/-1}.assistant-card-label{color:#64748b;font-size:11px;font-weight:500;letter-spacing:.01em;line-height:1.25}.assistant-card-value{color:#0f172a;font-size:14px;font-weight:600;line-height:1.4;overflow-wrap:anywhere}.assistant-card-metric[data-tone=positive] .assistant-card-value{color:#047857}.assistant-card-metric[data-tone=warning] .assistant-card-value{color:#b45309}.assistant-card :is(strong,b){font-weight:600}.assistant-card>footer{padding:0 16px 14px}:host ::ng-deep .assistant-markdown{line-height:1.45}:host ::ng-deep .assistant-markdown>:first-child{margin-top:0}:host ::ng-deep .assistant-markdown>:last-child{margin-bottom:0}:host ::ng-deep .assistant-markdown p{margin:0 0 8px}:host ::ng-deep .assistant-markdown ul,:host ::ng-deep .assistant-markdown ol{margin:8px 0;padding-left:22px}:host ::ng-deep .assistant-markdown li+li{margin-top:4px}:host ::ng-deep .assistant-markdown strong{font-weight:700}:host ::ng-deep .assistant-markdown code{padding:1px 4px;border-radius:4px;background:#e2e8f0;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:.9em}:host ::ng-deep .assistant-markdown a{color:var(--primary-color, #2563eb);text-decoration:underline}.assistant-status{display:inline-flex;margin-top:8px;padding:3px 8px;border-radius:999px;color:#475569;background:#e2e8f0;font-size:11px;font-weight:600;text-transform:capitalize}.pending-action{display:grid;gap:9px;margin-top:12px;padding:12px;border:1px solid #f59e0b;border-radius:12px;background:#fffbeb}.pending-action-heading{display:flex;align-items:center;justify-content:space-between;color:#92400e}.pending-action-heading span{padding:2px 7px;border-radius:999px;color:#78350f;background:#fde68a;font-size:11px;font-weight:700}.pending-action small{color:#78716c}.pending-action-buttons{display:flex;gap:8px}.action-decision{color:#475569;font-weight:600}.assistant-sources{display:grid;gap:4px;margin-top:12px;padding-top:10px;border-top:1px solid #e2e8f0;color:#64748b;font-size:12px}.assistant-shift-groups,.assistant-shift-group{display:grid;gap:10px}.assistant-shift-groups,.assistant-rota{margin-top:12px}.assistant-shift-group h3,.assistant-rota h3{margin:0;color:#0f172a;font-size:13px;font-weight:600}.assistant-shift-card-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:9px}.assistant-rota{display:grid;gap:10px}.assistant-rota-heading{display:grid;gap:8px}.assistant-rota-summary{display:flex;flex-wrap:wrap;gap:7px}.assistant-rota-summary>span{display:grid;gap:2px;min-width:86px;padding:7px 9px;border:1px solid #e2e8f0;border-radius:8px;background:#f8fafc}.assistant-rota-summary small{color:#64748b;font-size:9px;font-weight:600;text-transform:uppercase}.assistant-rota-summary strong{color:#334155;font-size:11px}.assistant-rota-scroll{max-width:100%;overflow-x:auto;border:1px solid #e2e8f0;border-radius:10px;background:#fff}.assistant-rota-week{min-width:1288px}.assistant-rota-week+.assistant-rota-week{border-top:1px solid #cbd5e1}.assistant-rota-week-heading{display:flex;align-items:center;justify-content:space-between;padding:8px 10px;color:#334155;background:#f1f5f9}.assistant-rota-week-heading strong{font-size:12px}.assistant-rota-week-heading span{color:#64748b;font-size:10px}.assistant-rota-week-grid{display:grid;grid-template-columns:repeat(7,minmax(184px,1fr))}.assistant-rota-day{min-width:0;min-height:120px;border-right:1px solid #e2e8f0}.assistant-rota-day:last-child{border-right:0}.assistant-rota-day>header{display:flex;align-items:baseline;justify-content:space-between;padding:7px 8px;border-bottom:1px solid #e2e8f0;color:#334155;background:#f8fafc}.assistant-rota-day>header strong{font-size:10px}.assistant-rota-day>header span{color:#64748b;font-size:9px}.assistant-rota-day-shifts{display:grid;gap:7px;padding:7px}.assistant-rota-empty,.assistant-rota-no-weeks{margin:0;color:#94a3b8;font-size:10px;font-style:italic}.assistant-visualisations{display:grid;gap:10px;margin-top:12px}.assistant-visualisation{display:grid;gap:12px;padding:13px;border:1px solid #dbeafe;border-radius:14px;background:linear-gradient(145deg,#f8fbff,#fff)}.assistant-visualisation h3{margin:0;color:#0f172a;font-size:13px;font-weight:600}.assistant-export-heading{display:flex;min-width:0;gap:8px;align-items:center}.assistant-export-heading h3{min-width:0}.assistant-export-action{flex:0 0 auto;margin-left:auto;padding:0;color:inherit;background:transparent;border-color:transparent;box-shadow:none}:host ::ng-deep .assistant-export-action .p-button-icon{font-size:20px!important}.assistant-export-action-pdf{color:#d32f2f}.assistant-export-action-excel{color:#217346}.assistant-export-action-pdf:hover{color:#b71c1c;background:transparent;border-color:transparent}.assistant-export-action-excel:hover{color:#185c37;background:transparent;border-color:transparent}.assistant-doughnut-layout{display:grid;grid-template-columns:112px minmax(0,1fr);gap:14px;align-items:center}.assistant-doughnut{position:relative;display:grid;place-items:center;width:112px;aspect-ratio:1}.assistant-doughnut svg{width:100%;height:100%;transform:rotate(-90deg)}.assistant-doughnut circle{fill:none;stroke-width:6}.assistant-doughnut-track{stroke:#e2e8f0}.assistant-doughnut-segment{transition:stroke-dasharray .18s ease}.assistant-doughnut>span{position:absolute;display:grid;color:#64748b;font-size:9px;line-height:1.1;text-align:center}.assistant-doughnut>span strong{color:#0f172a;font-size:18px}.assistant-chart-legend{display:grid;gap:7px;min-width:0}.assistant-chart-legend-item{display:grid;grid-template-columns:9px minmax(0,1fr) auto;gap:7px;align-items:center;color:#475569;font-size:11px}.assistant-chart-legend-item i{width:9px;height:9px;border-radius:999px}.assistant-chart-legend-item strong,.assistant-bar-label strong{color:#0f172a;font-size:11px;font-weight:600}.assistant-bar-chart,.assistant-bar-row{display:grid;gap:6px}.assistant-bar-chart{gap:11px}.assistant-bar-label{display:flex;gap:12px;align-items:baseline;justify-content:space-between;color:#475569;font-size:11px}.assistant-bar-track{height:9px;overflow:hidden;border-radius:999px;background:#e2e8f0}.assistant-bar-track i{display:block;height:100%;min-width:0;border-radius:var(--max-frame-radius, 0);transition:width .18s ease}.assistant-tables{display:grid;gap:10px;margin-top:12px}.assistant-table-section{display:grid;gap:6px}.assistant-table-section h3{margin:0;color:#0f172a;font-size:13px;font-weight:600}.assistant-table-wrap{overflow:auto;max-height:450px;border:1px solid var(--border-color, #e2e8f0);border-radius:var(--border-radius, 6px)}.assistant-table-wrap table{width:100%;min-width:420px;border-collapse:collapse;background:#fff}.assistant-table-wrap th,.assistant-table-wrap td{padding:8px 10px;border-bottom:1px solid var(--border-color, #e2e8f0);color:#334155;font-size:12px;line-height:1.35;text-align:left;vertical-align:top}.assistant-table-wrap th{position:sticky;z-index:1;top:0;color:#475569;font-weight:600;background:#f8fafc}.assistant-table-wrap tr:last-child td{border-bottom:0}.assistant-table-actions{display:flex;flex-wrap:wrap;gap:6px;min-width:150px}.details-toggle{display:flex;width:fit-content;margin:10px 0 0 auto;padding:0;border:0;color:var(--primary-color, #2563eb);background:transparent;font:inherit;font-size:13px;font-weight:400;text-decoration:underline;text-underline-offset:3px;cursor:pointer}.details-toggle:hover{color:var(--primary-dark-color, #1d4ed8)}.details-toggle:focus-visible{outline:2px solid var(--primary-color, #2563eb);outline-offset:3px}.developer-details{display:grid;gap:12px;margin-top:12px;padding:12px;border:1px solid var(--border-color, #e2e8f0);border-radius:10px;background:#f8fafc}.developer-details-header h3,.developer-details-header p{margin:0}.developer-details-header h3{color:#0f172a;font-size:13px;font-weight:600}.developer-details-header p{margin-top:2px;color:#64748b;font-size:11px}.workflow-trace{display:grid;gap:0;margin:0;padding:0;list-style:none}.workflow-step{display:block;min-width:0}.workflow-category{color:#64748b;font-size:9px;font-weight:600;letter-spacing:.06em;text-transform:uppercase}.workflow-meta{display:grid;flex:0 0 auto;gap:2px;justify-items:end;color:#64748b;font-size:9px}.workflow-status{padding:2px 5px;border-radius:999px;color:#334155;background:#e2e8f0;font-weight:600;text-transform:capitalize}.workflow-step[data-status=succeeded] .workflow-status{color:#166534;background:#dcfce7}.workflow-step[data-status=failed] .workflow-status{color:#991b1b;background:#fee2e2}.trace-json{display:grid;gap:4px;margin-top:8px}.trace-json>span{color:#64748b;font-size:10px;font-weight:600;text-transform:uppercase}.trace-json pre{max-height:280px;margin:0;padding:8px;overflow:auto;border-radius:6px;color:#dbeafe;background:#0f172a;font-size:10px;line-height:1.45;white-space:pre-wrap;overflow-wrap:anywhere}.trace-error{display:grid;gap:3px;margin-top:8px;padding:8px;border-left:3px solid #dc2626;border-radius:4px;color:#991b1b;background:#fef2f2;font-size:11px}.developer-details-header{display:flex;gap:12px;align-items:flex-start;justify-content:space-between}.developer-eyebrow{color:var(--text-color, #0f172a);font-size:9px;font-weight:600;letter-spacing:.08em;text-transform:uppercase}.trace-section-label{color:var(--text-color, #0f172a);font-size:9px;font-weight:600;text-decoration:underline;text-underline-offset:3px}.trace-run-summary{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:7px}.trace-metric{display:grid;gap:3px;min-width:0;padding:9px;border:1px solid #e2e8f0;border-radius:8px;background:#fff}.trace-metric span,.trace-loop-policy span{color:#64748b;font-size:9px;font-weight:600}.trace-metric strong{color:#0f172a;font-size:13px}.trace-loop-policy{display:grid;grid-template-columns:minmax(0,1fr) auto;grid-column:1/-1;gap:5px 12px;align-items:center;padding:10px;border:1px solid #c7d2fe;border-radius:9px;background:#eef2ff}.trace-loop-policy div{display:grid;gap:2px}.trace-loop-policy strong{color:#312e81;font-size:11px}.trace-loop-policy p{grid-column:1/-1;margin:0;color:#475569;font-size:10px;line-height:1.45}.trace-no-loop{padding:3px 7px;border-radius:999px;color:#166534!important;background:#dcfce7;font-weight:600!important}.workflow-summary{margin:9px 0 0;color:#475569;font-size:10.5px;line-height:1.5}.trace-technology{display:grid;gap:6px;margin-top:10px;padding:8px;border:1px solid #dbeafe;border-radius:7px;background:#f8fbff}.trace-inline-facts{display:flex;flex-wrap:wrap;gap:5px}.trace-inline-facts>span{display:grid;gap:1px;max-width:100%;padding:4px 6px;border-radius:5px;color:#1e293b;background:#fff;font-size:9.5px;overflow-wrap:anywhere}.trace-inline-facts small{color:#64748b;font-size:8px;font-weight:600;text-transform:uppercase}.trace-control{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:4px 8px;margin-top:8px;padding:8px;border-left:3px solid #8b5cf6;border-radius:5px;background:#f5f3ff}.trace-control>div{display:grid;gap:2px}.trace-control strong,.trace-control>span{color:#5b21b6;font-size:9.5px}.trace-control p{grid-column:1/-1;margin:0;color:#475569;font-size:9.5px;line-height:1.4}.trace-query,.trace-section,.trace-arguments,.trace-ranking-wrap{display:grid;gap:5px;margin-top:10px}.trace-query>span,.trace-transform>div>span,.trace-vector>span,.trace-payload-grid section>span,.trace-tool-call>span,.trace-supabase-call span,.trace-decision>span{color:#64748b;font-size:9px;font-weight:600;text-transform:uppercase}.trace-query>span,.trace-vector>span,.trace-payload-grid section>span,.trace-tool-call>span,.trace-decision>span{color:var(--text-color, #0f172a);text-decoration:underline;text-underline-offset:3px}.trace-query blockquote{margin:0;padding:8px 10px;border-left:3px solid #2563eb;border-radius:5px;color:#172554;background:#eff6ff;font-size:11px;font-weight:600;line-height:1.45}.trace-query-compact blockquote{border-color:#8b5cf6;color:#4c1d95;background:#f5f3ff}.trace-card-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:7px;margin-top:9px}.trace-data-card{min-width:0;padding:8px;border:1px solid #e2e8f0;border-radius:7px;background:#f8fafc}.trace-data-card-accent{border-color:#bfdbfe;background:#eff6ff}.trace-data-card h5{margin:0 0 5px;color:var(--text-color, #0f172a);font-size:10px;font-weight:600;text-decoration:underline;text-underline-offset:3px}.trace-field-list,.trace-argument-grid{display:grid;gap:4px;margin:0}.trace-field-list>div{display:grid;grid-template-columns:minmax(70px,.7fr) minmax(0,1.3fr);gap:6px}.trace-field-list dt,.trace-argument-grid dt{color:#64748b;font-size:8.5px}.trace-field-list dd,.trace-argument-grid dd{margin:0;color:#1e293b;font-size:9px;font-weight:600;overflow-wrap:anywhere}.trace-transform{display:grid;grid-template-columns:minmax(0,1fr) 18px minmax(0,1fr);gap:6px;align-items:stretch;margin-top:10px}.trace-transform>div{display:grid;gap:5px;padding:9px;border:1px solid #e2e8f0;border-radius:7px;background:#f8fafc}.trace-transform .trace-transform-result{border-color:#bfdbfe;background:#eff6ff}.trace-transform p{margin:0;color:#1e293b;font-size:10px;font-weight:600;line-height:1.4}.trace-transform-arrow{display:grid;place-items:center;color:#2563eb;font-size:16px;font-weight:600}.trace-entity-list{display:flex;flex-wrap:wrap;gap:5px}.trace-entity-list>span{display:flex;gap:5px;align-items:center;padding:4px 7px;border:1px solid #fed7aa;border-radius:999px;color:#9a3412;background:#fff7ed;font-size:9.5px}.trace-entity-list small{color:#c2410c;font-size:7.5px;font-weight:600;text-transform:uppercase}.trace-stat-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px;margin-top:8px}.trace-stat-grid>div{display:grid;gap:2px;padding:7px;border:1px solid #e2e8f0;border-radius:6px}.trace-stat-grid span{color:#64748b;font-size:8.5px}.trace-stat-grid strong{color:#0f172a;font-size:10px;overflow-wrap:anywhere}.trace-vector{display:grid;gap:4px;margin-top:7px}.trace-vector code{padding:7px;overflow:auto;border-radius:5px;color:#c4b5fd;background:#1e1b4b;font-size:8.5px;white-space:nowrap}.trace-supabase-call{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px;margin-top:10px;padding:9px;border:1px solid #a7f3d0;border-radius:7px;background:#ecfdf5}.trace-supabase-call>div{display:grid;gap:2px}.trace-supabase-call strong{color:#065f46;font-size:10px;overflow-wrap:anywhere}.trace-table-list{grid-column:1/-1}.trace-table-list>div{display:flex;flex-wrap:wrap;gap:4px}.trace-table-list code{padding:3px 5px;border-radius:4px;color:#065f46;background:#d1fae5;font-size:8.5px}.trace-decision{display:grid;gap:4px;margin-top:7px;padding:9px;border-left:3px solid #16a34a;border-radius:5px;background:#f0fdf4}.trace-decision strong{color:#14532d;font-size:11px}.trace-decision div{display:flex;flex-wrap:wrap;gap:8px;color:#166534;font-size:8.5px}.trace-ranking-wrap{overflow:auto}.trace-ranking{width:100%;min-width:610px;border-collapse:collapse;font-size:8.5px}.trace-ranking th,.trace-ranking td{padding:6px;border-bottom:1px solid #e2e8f0;color:#475569;text-align:right;vertical-align:top}.trace-ranking th{color:#64748b;background:#f8fafc;font-size:8px;text-transform:uppercase}.trace-ranking th:nth-child(2),.trace-ranking td:nth-child(2){text-align:left}.trace-ranking td:nth-child(2){display:grid;gap:2px;min-width:145px}.trace-ranking strong{color:#1e293b;font-size:9px}.trace-ranking code{color:#64748b;font-size:7.5px}.trace-argument-grid{grid-template-columns:repeat(2,minmax(0,1fr));margin-top:3px}.trace-argument-grid>div{min-width:0;padding:7px;border:1px solid #e2e8f0;border-radius:6px;background:#f8fafc}.trace-tool-call,.trace-api-route{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin-top:8px;padding:8px;border-radius:6px;color:#dbeafe;background:#0f172a}.trace-tool-call>span{width:100%;color:#94a3b8}.trace-tool-call strong{color:#bfdbfe;font-size:10px}.trace-tool-call pre,.trace-payload-grid pre{width:100%;max-height:220px;margin:0;overflow:auto;color:#dbeafe;font-size:9px;line-height:1.45;white-space:pre-wrap;overflow-wrap:anywhere}.trace-api-route>code{flex:1 1 180px;color:#e2e8f0;font-size:9px;overflow-wrap:anywhere}.trace-http-method,.trace-http-status{padding:3px 6px;border-radius:4px;color:#fff;background:#2563eb;font-size:8.5px;font-weight:600}.trace-http-status.success{color:#bbf7d0;background:#166534}.trace-http-status.error{color:#fecaca;background:#991b1b}.trace-payload-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px;margin-top:7px}.trace-payload-grid section{display:grid;gap:5px;min-width:0;padding:8px;border:1px solid #334155;border-radius:6px;background:#0f172a}.trace-payload-grid section>span{color:#94a3b8}.trace-error.trace-warning{border-left-color:#f59e0b;color:#92400e;background:#fffbeb}.trace-error-legacy{display:none}.trace-error-heading{font-size:10px}.details-dialog-backdrop{position:fixed;inset:0;z-index:20;display:grid;padding:14px;place-items:center;background:#0f172a7a;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}.details-dialog-backdrop .developer-details{display:block;width:100%;max-height:100%;margin:0;padding:0 14px 14px;overflow:auto;overscroll-behavior:contain;border:0;border-radius:14px;background:#fff;box-shadow:0 24px 70px #0f172a4d}.details-dialog-backdrop .developer-details-header{position:sticky;top:0;z-index:3;margin:0 -14px 14px;padding:14px;border-bottom:1px solid #e2e8f0;background:#fffffff7;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}.details-dialog-actions{display:flex;flex:0 0 auto;gap:7px;align-items:center}.details-dialog-close{display:grid;width:30px;height:30px;padding:0;place-items:center;border:1px solid #e2e8f0;border-radius:8px;color:#475569;background:#fff;cursor:pointer}.details-dialog-close:hover{color:#0f172a;background:#f1f5f9}.details-dialog-close:focus-visible{outline:2px solid #2563eb;outline-offset:2px}.details-dialog-backdrop .trace-run-summary{margin-bottom:6px;padding-bottom:14px;border-bottom:1px solid #cbd5e1}.details-dialog-backdrop .trace-metric{padding:0 9px;border:0;border-right:1px solid #e2e8f0;border-radius:0;background:transparent}.details-dialog-backdrop .trace-metric:nth-child(4){border-right:0}.details-dialog-backdrop .trace-loop-policy{margin-top:5px;padding:9px 0 0;border:0;border-top:1px solid #e2e8f0;border-radius:0;background:transparent}.details-dialog-backdrop .workflow-trace{display:block}.details-dialog-backdrop .workflow-step{display:block;border-bottom:1px solid #cbd5e1}.workflow-section{display:block}.workflow-step-toggle{display:flex;gap:14px;align-items:center;justify-content:space-between;width:100%;padding:14px 2px;border:0;color:inherit;background:transparent;font:inherit;text-align:left;cursor:pointer}.workflow-step-toggle:hover{background:#f8fafc}.workflow-step-toggle:focus-visible{outline:2px solid #2563eb;outline-offset:-2px}.workflow-step-toggle>div:first-child{display:grid;min-width:0;gap:2px}.workflow-step-toggle h4{margin:0;color:var(--text-color, #0f172a);font-size:12px;font-weight:600;line-height:1.4;text-decoration:underline;text-decoration-color:#94a3b8;text-underline-offset:4px}.workflow-step-number{display:block;color:var(--primary-color, #2563eb);font-size:13px;font-weight:600}.workflow-expand-icon{color:#64748b;font-size:10px}.workflow-step-content{padding:0 2px 16px}.details-dialog-backdrop .workflow-summary{margin-top:0;padding-bottom:10px;border-bottom:1px solid #e2e8f0}.details-dialog-backdrop .trace-technology,.details-dialog-backdrop .trace-control{padding:9px 0;border:0;border-bottom:1px solid #e2e8f0;border-radius:0;background:transparent}.details-dialog-backdrop .trace-control{border-left:0}.details-dialog-backdrop .trace-inline-facts>span{padding:0 8px 0 0;border-right:1px solid #e2e8f0;border-radius:0;background:transparent}.details-dialog-backdrop :is(h3,h4,h5,strong,.workflow-status,.trace-section-label,.developer-eyebrow){font-weight:600!important}@media (max-width: 520px){.trace-run-summary,.trace-card-grid,.trace-stat-grid,.trace-payload-grid,.trace-argument-grid,.trace-transform{grid-template-columns:1fr}.trace-transform-arrow{transform:rotate(90deg)}}.suggestions{display:grid;gap:0;margin-top:12px}.entity-options{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin-top:12px}.suggestion-chip{justify-content:flex-start;width:100%;padding:6px 0;border:1px solid transparent;border-radius:999px;color:var(--primary-color, #2563eb);background:transparent;font-weight:600;box-shadow:none;text-align:left;transition:padding .16s ease,border-color .16s ease,background .16s ease,box-shadow .16s ease}.suggestion-chip:hover{padding:6px 12px;border-color:rgba(var(--primary-color-rgb, 37, 99, 235),.28);color:var(--primary-color, #2563eb);background:rgba(var(--primary-color-rgb, 37, 99, 235),.08);box-shadow:0 4px 14px #0f172a0f}.response-details{display:grid;gap:12px;margin-top:12px}.response-section{display:grid;gap:8px;padding-bottom:12px;border-bottom:1px solid var(--border-color, #e2e8f0)}.response-section:last-child{padding-bottom:0;border-bottom:0}.response-section h3{margin:0;color:#0f172a;font-size:13px;font-weight:600}.quoted{padding:8px 10px;border-left:5px solid var(--primary-color, #2563eb);border-radius:var(--border-radius, 6px);color:#1e293b;background:#f8fafc}.detail-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;margin:0}.detail-grid div{min-width:0;padding:8px;border-radius:var(--border-radius, 6px);background:#f8fafc}.detail-grid dt{margin-bottom:3px;color:#64748b;font-size:11px;font-weight:600;text-transform:uppercase}.detail-grid dd{margin:0;color:#334155;font-size:13px;font-weight:600;line-height:1.35;overflow-wrap:anywhere}.detail-grid dd span{display:block;margin-top:2px;color:#64748b;font-size:11px}.api-call-summary,.json-block{display:grid;gap:6px;padding:8px;border-radius:var(--border-radius, 6px);background:#f8fafc}.api-call-summary .detail-label,.json-block .detail-label{color:#64748b;font-size:11px;font-weight:600;text-transform:uppercase}.api-call-summary code{color:var(--secondary-color, #0f172a);font-weight:600;white-space:normal;word-break:break-word}.json-block pre{max-height:220px;margin:0;overflow:auto;color:#0f172a;font-size:12px;line-height:1.45;white-space:pre-wrap;overflow-wrap:anywhere}.assistant-composer{padding:14px 16px 16px;border-top:1px solid rgba(226,232,240,.9);border-bottom:0;box-shadow:0 -10px 30px #0f172a0a}.assistant-composer textarea{flex:1;min-height:46px;max-height:120px;border-radius:18px;background:#fff;resize:vertical}.assistant-composer button[type=submit]{width:44px;height:44px;border-radius:16px}@keyframes pulse{to{opacity:.35;transform:translateY(-2px)}}@media (prefers-reduced-motion: reduce){.mascot-aura,.mascot-art,.mascot-eye,.mascot-signal,.mascot-sparkle,.assistant-launcher:hover .mascot-art,.assistant-launcher:focus-visible .mascot-art,.assistant-launcher:hover .mascot-ear-right,.assistant-launcher:focus-visible .mascot-ear-right{animation:none}.assistant-launcher,.mascot{transition-duration:.01ms}}@media (max-width: 640px){.assistant-messages{padding:14px}.detail-grid,.entity-options,.assistant-card-metrics{grid-template-columns:1fr}.assistant-card-metric{padding:0}}\n", ":host{--max-accent: var(--max-assistant-accent, #1a73e8);--max-accent-strong: var(--max-assistant-accent-strong, #1557b0);--max-canvas: var(--max-assistant-canvas, #f8f9fa);--max-surface: var(--max-assistant-surface, #ffffff);--max-surface-soft: color-mix(in srgb, var(--max-accent) 6%, var(--max-surface));--max-text: var(--max-assistant-text, #1f1f1f);--max-muted: var(--max-assistant-muted, #5f6368);--max-border: var(--max-assistant-border, #dfe1e5);--max-success: var(--max-assistant-success, #188038);--max-warning: var(--max-assistant-warning, #b06000);--max-danger: var(--max-assistant-danger, #b3261e);--max-support-text: var(--max-assistant-support-text, #3c4043);--max-control-radius: var(--max-assistant-control-radius, 6px);--max-frame-radius: var(--max-assistant-frame-radius, 0px);--max-sparkles-gradient: linear-gradient( 135deg, color-mix(in srgb, var(--max-accent) 58%, white) 0%, var(--max-accent) 46%, color-mix(in srgb, var(--max-accent) 55%, var(--max-accent-strong)) 72%, var(--max-accent-strong) 100% );--max-header-action-size: 40px;--max-header-content-size: 20px;--primary-color: var(--max-accent);--primary-color-rgb: var(--max-assistant-accent-rgb, 26, 115, 232);--primary-dark-color: var(--max-accent-strong);--background: var(--max-canvas);--background-color: var(--max-canvas);--panel-background: var(--max-surface);--text-color: var(--max-text);--text-color-secondary: var(--max-muted);--border-color: var(--max-border);--success-color: var(--max-success);--warning-color: var(--max-warning);--error-color: var(--max-danger);--danger-color: var(--max-danger);--border-radius: var(--max-control-radius);position:relative;display:block;width:100%;height:100%;min-height:0;isolation:isolate;color:var(--max-text);font-family:Arial,Helvetica,sans-serif;font-size:16px;font-weight:400;line-height:normal;text-align:left;color-scheme:light}:host,:host *{box-sizing:border-box}:host button,:host ::ng-deep .p-button-label{text-transform:capitalize}.max-assistant-sparkles{display:inline-flex;flex:0 0 auto;align-items:center;justify-content:center;font-size:var(--max-header-content-size);line-height:1;vertical-align:middle;color:transparent;background:var(--assistant-sparkles-gradient, var(--max-sparkles-gradient));background-clip:text;-webkit-background-clip:text;-webkit-text-fill-color:transparent;filter:drop-shadow(0 2px 3px rgba(60,64,67,.18))}.assistant-window{position:relative;inset:auto;width:100%;height:100%;max-height:none;overflow:hidden;opacity:1;visibility:visible;pointer-events:auto;translate:none;transform:none;border:0;border-radius:var(--max-frame-radius);background:var(--max-canvas);box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none;transition:none}.assistant-panel{grid-template-rows:72px minmax(0,1fr) auto;color:var(--max-text);background:radial-gradient(circle at 48% 0%,color-mix(in srgb,var(--max-accent) 10%,transparent),transparent 46%),radial-gradient(circle at 92% 72%,color-mix(in srgb,#c58af9 8%,transparent),transparent 38%),linear-gradient(145deg,var(--max-canvas),color-mix(in srgb,var(--max-canvas) 94%,#edf3ff))}.assistant-header{display:flex;gap:20px;align-items:center;padding:0 24px;border:0;border-bottom:1px solid var(--max-border);background:color-mix(in srgb,var(--max-canvas) 88%,transparent);-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px)}.assistant-header-actions{display:flex;gap:4px;align-items:center;margin-left:auto}.assistant-identity{display:flex;flex-direction:column}.assistant-name{align-self:flex-start;margin:0;color:transparent;background:var(--assistant-sparkles-gradient, var(--max-sparkles-gradient));background-clip:text;-webkit-background-clip:text;-webkit-text-fill-color:transparent;font:inherit;font-size:var(--max-header-content-size);font-weight:600;line-height:1}.assistant-subtitle{color:var(--max-muted);font-size:12px;font-weight:400;letter-spacing:0;line-height:1;text-transform:none}.assistant-name-row{display:flex;align-items:center;gap:8px}.assistant-beta-tag{padding:3px 6px;color:var(--max-text-color, #475569);font-size:11px;font-weight:700;line-height:1;background:var(--max-accent-color, #e2e8f0);border-radius:4px}.assistant-header .header-action{display:inline-flex;width:var(--max-header-action-size);min-width:var(--max-header-action-size);height:var(--max-header-action-size);align-items:center;justify-content:center;margin:0;padding:0;appearance:none;border:0;border-radius:50%;color:var(--max-muted);background:transparent;font:inherit;line-height:1;cursor:pointer}.assistant-header .header-action-icon{font-size:var(--max-header-content-size);font-weight:400;line-height:1}.assistant-header .header-action:hover{color:var(--max-text);background:var(--max-surface-soft)}.assistant-header .header-action:focus-visible{outline:2px solid var(--max-accent);outline-offset:2px}.assistant-messages{width:min(820px,100%);min-height:0;justify-self:center;box-sizing:border-box;padding:44px 28px 32px;overflow-x:hidden;overflow-y:auto;scrollbar-color:color-mix(in srgb,var(--max-muted) 25%,transparent) transparent;scrollbar-width:thin}.assistant-table-wrap,.assistant-rota-scroll{scrollbar-color:color-mix(in srgb,var(--max-muted) 25%,transparent) transparent;scrollbar-width:thin}.assistant-messages::-webkit-scrollbar-thumb,.assistant-table-wrap::-webkit-scrollbar-thumb,.assistant-rota-scroll::-webkit-scrollbar-thumb{background:color-mix(in srgb,var(--max-muted) 25%,transparent)}.message{width:100%;max-width:100%;box-sizing:border-box;margin:0 0 34px;padding:0;border:0;border-radius:0;color:var(--max-text);background:transparent;box-shadow:none}.message.assistant{width:100%;max-width:100%}.message.user{width:fit-content;max-width:min(76%,640px);margin:0 0 32px auto;padding:13px 18px;border:1px solid var(--max-border);border-radius:18px 18px 6px;color:var(--max-text);background:linear-gradient(135deg,color-mix(in srgb,var(--max-accent) 10%,var(--max-surface)),color-mix(in srgb,var(--max-accent) 5%,var(--max-surface)));box-shadow:0 1px 2px color-mix(in srgb,var(--max-text) 7%,transparent),0 6px 18px color-mix(in srgb,var(--max-accent) 8%,transparent)}.message.user p{color:inherit;font-size:15px;line-height:1.55}.message.error{padding-left:16px;border-left:3px solid var(--max-danger)}.message.streaming{display:flex;gap:10px;align-items:center;padding:0;color:var(--max-muted);background:transparent;font-style:normal}.message.streaming:before{width:16px;height:16px;flex:0 0 auto;border-radius:6px;background:var(--assistant-sparkles-gradient, var(--max-sparkles-gradient));content:\"\";animation:max-thinking 1.4s ease-in-out infinite alternate}.streaming-progress{color:var(--max-muted);font-size:14px;white-space:pre-line}.message p,.assistant-result,:host ::ng-deep .assistant-markdown{color:var(--max-text);font-size:15px;line-height:1.65}:host ::ng-deep .assistant-markdown code{color:var(--max-text);background:color-mix(in srgb,var(--max-muted) 10%,transparent)}.message.welcome{min-height:260px;margin:0;padding-top:clamp(28px,8vh,90px);text-align:center}.message.welcome .assistant-markdown{max-width:650px;margin:0 auto}:host ::ng-deep .message.welcome .assistant-markdown p{margin:0;font-size:clamp(28px,3.2vw,42px);font-weight:500;letter-spacing:-.04em;line-height:1.18}:host ::ng-deep .message.welcome-message .assistant-markdown p{color:var(--max-accent)}.welcome-description{max-width:620px;margin:0 auto!important;margin-top:2rem!important;color:var(--max-text);font-size:16px;line-height:1.6;white-space:pre-line}.support-welcome-card{display:flex;width:min(460px,100%);min-height:70px;gap:13px;align-items:center;margin:22px auto 0;padding:13px 16px;appearance:none;border:1px solid color-mix(in srgb,var(--max-accent) 24%,var(--max-border));border-radius:16px;color:var(--max-support-text);background:linear-gradient(135deg,color-mix(in srgb,var(--max-accent) 10%,var(--max-surface)),var(--max-surface) 58%);box-shadow:0 8px 28px #3c40431a;font:inherit;text-align:left;cursor:pointer;transition:border-color .16s ease,box-shadow .16s ease,transform .16s ease}.support-welcome-card:hover{border-color:color-mix(in srgb,var(--max-accent) 48%,var(--max-border));box-shadow:0 12px 32px #3c404324;transform:translateY(-1px)}.support-welcome-card:focus-visible,.support-ticket-shortcut:focus-visible,.support-ticket-close:focus-visible,.response-feedback-action:focus-visible{outline:2px solid var(--max-accent);outline-offset:2px}.support-welcome-icon,.support-ticket-header-icon,.support-ticket-success-icon{display:inline-flex;width:40px;height:40px;flex:0 0 40px;align-items:center;justify-content:center;border-radius:13px;color:var(--max-accent);background:color-mix(in srgb,var(--max-accent) 13%,var(--max-surface));font-size:18px}.support-welcome-copy{display:flex;min-width:0;flex:1;flex-direction:column;gap:5px}.support-welcome-copy strong{color:var(--max-support-text);font-size:15px;font-weight:600;line-height:1.25}.support-welcome-copy small{color:var(--max-muted);font-size:12px;line-height:1.45}.support-welcome-arrow{flex:0 0 auto;color:var(--max-accent);font-size:16px}@media (min-width: 641px) and (max-height: 850px){.message.welcome{min-height:0;padding-top:22px;padding-bottom:22px}:host ::ng-deep .message.welcome .assistant-markdown p{font-size:clamp(24px,3vw,34px)}.welcome-description{margin-top:1rem!important;font-size:14px;line-height:1.45}.support-welcome-card{min-height:58px;margin-top:14px;padding:10px 13px}}.assistant-cards{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin-top:20px}.assistant-card{overflow:hidden;border:1px solid var(--max-border);border-radius:18px;background:var(--max-surface);box-shadow:none}.assistant-card>header{gap:4px;padding:16px;border-bottom:1px solid var(--max-border)}.assistant-card>header strong{color:var(--max-text);font-size:15px;font-weight:600}.assistant-card>header span,.assistant-card>footer,.assistant-card-metric span{color:var(--max-muted)}.assistant-card-metric{padding:14px;border-color:var(--max-border)}.assistant-card-metric strong{color:var(--max-text);font-size:10px}.assistant-card-metric[data-tone=positive] strong{color:var(--max-success)}.assistant-card-metric[data-tone=warning] strong{color:var(--max-warning)}.assistant-card>footer{padding:10px 16px;border-color:var(--max-border);background:var(--max-surface-soft)}.assistant-search-result>header{display:flex;gap:12px;align-items:center}.assistant-search-result-icon{display:inline-flex;width:36px;height:36px;flex:0 0 36px;align-items:center;justify-content:center;border-radius:12px;color:var(--max-accent);background:var(--max-surface-soft);font-size:16px;font-weight:400;line-height:1}.assistant-search-result-copy{display:grid;min-width:0;gap:4px}.assistant-search-result .suggestions{display:grid;grid-template-columns:repeat(auto-fit,minmax(132px,1fr));gap:10px;margin:0;padding:16px}.assistant-search-result .suggestion-chip{width:100%;min-height:44px;align-items:center;justify-content:flex-start;padding:10px 14px;border-color:var(--max-border);background:var(--max-surface-soft);line-height:1.25}.assistant-search-result .suggestion-chip:hover{padding:10px 14px;background:color-mix(in srgb,var(--max-accent) 10%,var(--max-surface))}:host ::ng-deep .assistant-search-result .suggestion-chip .p-button-icon{font-weight:400;line-height:1}.assistant-status{margin-top:12px;padding:0;border-radius:0;color:var(--max-muted);background:transparent;font-size:11px;letter-spacing:.05em;text-transform:uppercase}.pending-action{gap:12px;margin-top:18px;padding:18px;border:1px solid color-mix(in srgb,var(--max-warning) 38%,var(--max-border));border-radius:18px;background:color-mix(in srgb,var(--max-warning) 6%,var(--max-surface))}.pending-action-heading{color:var(--max-text)}.pending-action-heading span{color:var(--max-warning);background:transparent}.pending-action small,.action-decision{color:var(--max-muted)}.assistant-sources{margin-top:20px;padding-top:14px;border-color:var(--max-border);color:var(--max-muted)}.assistant-shift-groups,.assistant-rota{margin-top:20px}.assistant-shift-group h3,.assistant-rota h3,.assistant-rota-summary strong,.assistant-rota-week-heading,.assistant-rota-day>header{color:var(--max-text)}.assistant-rota-summary>span,.assistant-rota-scroll{border-color:var(--max-border);background:var(--max-surface)}.assistant-rota-summary small,.assistant-rota-week-heading span,.assistant-rota-day>header span{color:var(--max-muted)}.assistant-rota-week-heading,.assistant-rota-day>header{background:var(--max-surface-soft)}.assistant-rota-week+.assistant-rota-week,.assistant-rota-day,.assistant-rota-day>header{border-color:var(--max-border)}.assistant-visualisations{grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin-top:20px}.assistant-visualisation{padding:16px;border-color:var(--max-border);border-radius:18px;background:var(--max-surface)}.assistant-visualisation h3,.assistant-doughnut>span strong,.assistant-chart-legend-item strong,.assistant-bar-label strong{color:var(--max-text)}.assistant-chart-legend-item,.assistant-bar-label,.assistant-doughnut>span{color:var(--max-muted)}.assistant-doughnut-track,.assistant-bar-track{stroke:var(--max-border);background:var(--max-border)}.sources span{color:var(--max-muted)}.assistant-tables{gap:18px;margin-top:20px}.assistant-table-section{gap:10px}.assistant-table-section h3{color:var(--max-text);font-size:14px}.assistant-table-wrap{border-color:var(--max-border);border-radius:16px}.assistant-table-wrap table{background:var(--max-surface)}.assistant-table-wrap th,.assistant-table-wrap td{padding:11px 13px;border-color:var(--max-border);color:var(--max-text);font-size:12px}.assistant-table-wrap th{color:var(--max-muted);background:var(--max-surface-soft)}.details-toggle{margin:0 0 0 auto;color:var(--max-accent);font-size:12px;text-decoration:underline;text-underline-offset:3px}.details-toggle:hover{color:var(--max-accent-strong);text-decoration:underline}.suggestions{display:flex;flex-wrap:wrap;gap:8px;margin-top:18px}.capability-options{display:grid;gap:22px;margin-top:18px}.clarification-options{margin-top:18px}.capability-option-section{display:grid;gap:10px}.capability-option-section h3{margin:0;color:var(--max-text);font-size:14px;font-weight:600}.capability-option-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}.capability-option-card{display:grid;grid-template-columns:auto minmax(0,1fr) auto;gap:10px;width:100%;min-height:76px;padding:12px 14px;align-items:center;border:1px solid var(--max-border);border-radius:var(--border-radius, 6px);color:var(--max-text);background:var(--max-surface);box-shadow:none;text-align:left}.capability-option-card:hover:not(:disabled){border-color:color-mix(in srgb,var(--max-accent) 32%,var(--max-border));color:var(--max-text);background:var(--max-surface-soft);box-shadow:none}.capability-option-number{display:inline-flex;min-width:24px;height:24px;align-items:center;justify-content:center;border-radius:50%;color:var(--max-accent-strong);background:var(--max-surface-soft);font-size:12px;font-weight:600}.capability-option-copy{line-height:1.4}.capability-option-arrow{color:var(--max-muted);font-size:13px}.response-actions{display:flex;align-items:center;margin-top:8px}.response-feedback-action{display:inline-flex;width:32px;height:32px;align-items:center;justify-content:center;padding:0;appearance:none;border:0;border-radius:50%;color:var(--max-muted);background:transparent;font:inherit;cursor:pointer}.response-feedback-action:hover{color:var(--max-accent);background:var(--max-surface-soft)}.suggestion-chip{justify-content:flex-start;width:auto;min-height:40px;padding:8px 14px;border:1px solid var(--max-border);border-radius:14px;color:var(--max-text);background:var(--max-surface);font-weight:400;box-shadow:none;text-align:left}.suggestion-chip:hover{padding:8px 14px;border-color:color-mix(in srgb,var(--max-accent) 28%,var(--max-border));color:var(--max-text);background:var(--max-surface-soft);box-shadow:none}.message.welcome .suggestions{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin-top:0}.message.welcome .suggestion-chip{width:100%;min-height:74px;padding:14px 16px;align-items:flex-start;border-radius:18px;line-height:1.35}.message.welcome .suggestion-chip:hover{padding:14px 16px;transform:translateY(-1px)}.assistant-footer{display:flex;width:min(780px,100% - 48px);flex-direction:column;align-items:flex-end;justify-self:center}.support-ticket-shortcut{display:inline-flex;min-height:34px;gap:7px;align-items:center;margin:0 10px 9px 0;padding:7px 12px;appearance:none;border:1px solid color-mix(in srgb,var(--max-accent) 24%,var(--max-border));border-radius:999px;color:var(--max-accent-strong);background:color-mix(in srgb,var(--max-accent) 7%,var(--max-surface));box-shadow:0 2px 8px #3c404314;font:inherit;font-size:13px;font-weight:600;line-height:1;cursor:pointer}.support-ticket-shortcut:hover{border-color:color-mix(in srgb,var(--max-accent) 45%,var(--max-border));background:color-mix(in srgb,var(--max-accent) 11%,var(--max-surface))}.support-ticket-shortcut i{font-size:15px}.assistant-composer{display:flex;width:100%;box-sizing:border-box;gap:8px;align-items:center;margin:0 0 24px;padding:8px 8px 8px 18px;border:1px solid var(--max-border);border-radius:28px;background:var(--max-surface);box-shadow:0 1px 2px #3c404314,0 6px 20px #3c40431a;transition:border-color .16s ease,box-shadow .16s ease}.assistant-composer:focus-within{border-color:color-mix(in srgb,var(--max-accent) 36%,var(--max-border));box-shadow:0 1px 2px #3c404314,0 8px 24px #3c404324}.assistant-composer textarea{flex:1;min-height:44px;height:44px;max-height:132px;box-sizing:border-box;padding:11px 2px;border:0;border-radius:0;outline:0;color:var(--max-text);background:transparent;box-shadow:none;font:inherit;font-size:15px;line-height:22px;resize:none}.assistant-composer textarea::placeholder{color:var(--max-muted);opacity:.84}.assistant-composer textarea:focus{border:0;outline:0;box-shadow:none}.assistant-composer button[type=submit]{width:44px;height:44px;flex:0 0 auto;border-radius:50%;background:var(--max-accent)}.assistant-composer button[type=submit]:disabled{border-color:transparent;color:var(--max-muted);background:transparent;opacity:.5}.support-ticket-overlay{position:absolute;z-index:100;inset:0;display:flex;overflow:auto;align-items:flex-start;justify-content:center;padding:24px;background:#1f1f1f70;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.support-ticket-dialog{position:relative;display:flex;width:min(700px,100%);flex-direction:column;margin:auto 0;border:1px solid var(--max-border);border-radius:22px;color:var(--max-support-text);background:var(--max-surface);box-shadow:0 24px 72px #1f1f1f47}.feedback-dialog{max-height:calc(100% - 48px);overflow:hidden}.feedback-dialog .feedback-form{display:flex;min-height:0;flex:1 1 auto;flex-direction:column;overflow:hidden;padding:0}.feedback-header{position:sticky;z-index:2;top:0;flex:0 0 auto;background:var(--max-surface)}.feedback-header p{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.feedback-form-body{min-height:0;flex:1 1 auto;padding:18px 22px;overflow-y:auto;overscroll-behavior:contain}.feedback-form .support-ticket-fields{gap:12px 18px}.feedback-form .support-ticket-field{gap:5px}.feedback-form .support-ticket-field textarea{min-height:72px}.feedback-actions{position:sticky;z-index:2;bottom:0;flex:0 0 auto;margin:0;padding:14px 22px;border-top:1px solid var(--max-border);background:var(--max-surface)}.support-ticket-header{display:flex;gap:14px;align-items:center;padding:20px 22px;border-bottom:1px solid var(--max-border)}.support-ticket-header-icon{width:44px;height:44px;flex-basis:44px;border-radius:14px;font-size:19px}.support-ticket-header>div{min-width:0;flex:1}.support-ticket-header h2,.support-ticket-header p,.support-ticket-success h3,.support-ticket-success p{margin:0}.support-ticket-header h2{color:var(--max-support-text);font-size:19px;font-weight:600;line-height:1.3}.support-ticket-header p{margin-top:3px;color:var(--max-muted);font-size:13px;line-height:1.4}.support-ticket-close{display:inline-flex;width:38px;height:38px;flex:0 0 38px;align-items:center;justify-content:center;padding:0;appearance:none;border:0;border-radius:50%;color:var(--max-muted);background:transparent;font:inherit;cursor:pointer}.support-ticket-close:hover{color:var(--max-support-text);background:var(--max-surface-soft)}.support-ticket-form{min-height:0;overflow:visible;padding:22px}.support-ticket-fields{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:18px}.support-ticket-field{display:flex;min-width:0;flex-direction:column;gap:7px;color:var(--max-support-text);font-size:13px;font-weight:600}.support-ticket-field>span{display:flex;gap:5px;align-items:baseline}.support-ticket-field>span small{color:var(--max-muted);font-size:11px;font-weight:400}.support-ticket-field-wide{grid-column:1/-1}.support-ticket-field input,.support-ticket-field textarea{width:100%;min-height:44px;padding:10px 12px;border:1px solid var(--max-border);border-radius:10px;outline:0;color:var(--max-support-text);background:var(--max-surface);box-shadow:none;font:inherit;font-size:14px;font-weight:400;line-height:1.45}.support-ticket-field textarea{min-height:116px;resize:vertical}.support-ticket-field input[readonly],.support-ticket-field textarea[readonly]{color:color-mix(in srgb,var(--max-support-text) 82%,var(--max-muted));background:color-mix(in srgb,var(--max-muted) 6%,var(--max-surface));cursor:default}.support-ticket-field input::placeholder,.support-ticket-field textarea::placeholder{color:var(--max-muted);opacity:.82}.support-ticket-field input:focus,.support-ticket-field textarea:focus{border-color:var(--max-accent);box-shadow:0 0 0 3px color-mix(in srgb,var(--max-accent) 13%,transparent)}:host ::ng-deep .support-ticket-dialog .p-select,:host ::ng-deep .support-ticket-dialog .p-multiselect{min-height:44px;border-color:var(--max-border);border-radius:10px;color:var(--max-support-text);background:var(--max-surface);box-shadow:none;font:inherit;font-size:14px;font-weight:400}:host ::ng-deep .support-ticket-dialog .p-select:not(.p-disabled).p-focus,:host ::ng-deep .support-ticket-dialog .p-multiselect:not(.p-disabled).p-focus{border-color:var(--max-accent);box-shadow:0 0 0 3px color-mix(in srgb,var(--max-accent) 13%,transparent)}:host ::ng-deep .support-ticket-dialog .p-select-label,:host ::ng-deep .support-ticket-dialog .p-multiselect-label,:host ::ng-deep .support-ticket-dialog .p-select-dropdown,:host ::ng-deep .support-ticket-dialog .p-multiselect-dropdown{color:var(--max-support-text);font:inherit;font-size:14px}:host ::ng-deep .support-ticket-dialog .p-select-label,:host ::ng-deep .support-ticket-dialog .p-multiselect-label{display:flex;min-height:42px;align-items:center}:host ::ng-deep .support-ticket-dialog .p-multiselect-label{flex-wrap:wrap;gap:5px;padding-block:5px}:host ::ng-deep .support-selected-tags{display:inline-flex;min-width:0;flex-wrap:wrap;gap:5px;align-items:center}:host ::ng-deep .support-ticket-dialog .p-tag{font-size:12px;font-weight:600}:host ::ng-deep .support-ticket-dialog .p-tag-icon{font-size:11px}:host ::ng-deep .support-ticket-dialog .p-select-option,:host ::ng-deep .support-ticket-dialog .p-multiselect-option{color:var(--max-support-text)}:host ::ng-deep .support-ticket-dialog .p-select-overlay,:host ::ng-deep .support-ticket-dialog .p-multiselect-overlay{border-color:var(--max-border);border-radius:12px;color:var(--max-support-text);background:var(--max-surface);box-shadow:0 12px 32px #1f1f1f2e;font:inherit}.support-ticket-notice,.support-ticket-error{margin:16px 0 0;padding:10px 12px;border-radius:10px;font-size:13px;line-height:1.45}.support-ticket-notice{color:var(--max-warning);background:color-mix(in srgb,var(--max-warning) 9%,var(--max-surface))}.support-ticket-error{color:var(--max-danger);background:color-mix(in srgb,var(--max-danger) 8%,var(--max-surface))}.support-ticket-actions{display:flex;gap:10px;justify-content:flex-end;margin-top:22px}.support-ticket-success{display:flex;min-height:340px;align-items:center;justify-content:center;padding:38px 24px;flex-direction:column;text-align:center}.support-ticket-success-icon{width:64px;height:64px;flex-basis:64px;border-radius:50%;color:var(--max-success);background:color-mix(in srgb,var(--max-success) 12%,var(--max-surface));font-size:32px}.support-ticket-close i{font-size:20px}.support-ticket-success h3{margin-top:18px;color:var(--max-support-text);font-size:21px}.support-ticket-success p{max-width:420px;margin-top:7px;color:var(--max-muted);font-size:14px;line-height:1.5}.support-ticket-reference{display:flex;gap:6px;align-items:center;margin:22px 0;padding:10px 14px;border:1px solid var(--max-border);border-radius:10px;background:var(--max-surface-soft);font-size:13px}.support-ticket-reference span{color:var(--max-muted)}@keyframes max-thinking{0%{opacity:.55;transform:rotate(-8deg) scale(.86)}to{opacity:1;transform:rotate(8deg) scale(1)}}@media (prefers-reduced-motion: reduce){.message.streaming:before{animation:none}.suggestion-chip,.capability-option-card,.support-welcome-card{transition:none}}@media (max-width: 900px){.assistant-messages{padding-top:34px}}@media (max-width: 640px){.assistant-panel{grid-template-rows:64px minmax(0,1fr) auto}.assistant-header{padding:0 14px}.assistant-subtitle{display:none}.assistant-messages{padding:26px 18px 20px}.message.welcome{padding-top:24px}.message.welcome .suggestions,.assistant-cards,.assistant-visualisations,.capability-option-grid{grid-template-columns:1fr}.message.welcome .suggestion-chip{min-height:60px}.message.user{max-width:88%}.assistant-composer{width:100%;margin-bottom:12px}.assistant-footer{width:calc(100% - 24px)}.support-ticket-overlay{align-items:start;padding:10px}.support-ticket-dialog{max-height:none;border-radius:16px}.feedback-dialog{max-height:calc(100% - 20px)}.support-ticket-header{padding:16px}.support-ticket-header p{display:none}.feedback-header p{display:block}.feedback-form-body{padding:14px 16px}.feedback-actions{padding:12px 16px}.support-ticket-form{overflow:visible;padding:16px}.support-ticket-fields{grid-template-columns:1fr;gap:14px}.support-ticket-field-wide{grid-column:auto}.support-ticket-actions{flex-direction:column-reverse}.support-ticket-actions button{width:100%}}\n"] }]
|
|
1895
|
+
], encapsulation: ViewEncapsulation.Emulated, template: "<aside\n class=\"assistant-window\"\n [attr.aria-label]=\"uiCopy.title\"\n role=\"region\"\n>\n <section class=\"assistant-panel\">\n <header class=\"assistant-header\">\n <i class=\"max-assistant-sparkles far fa-sparkles\" aria-hidden=\"true\"></i>\n <div class=\"assistant-identity\">\n <div class=\"assistant-name-row\">\n <h2 class=\"assistant-name\">{{ uiCopy.title }}</h2>\n <span class=\"assistant-beta-tag\">Beta</span>\n </div>\n <span class=\"assistant-subtitle\">{{ uiCopy.subtitle }}</span>\n </div>\n <div class=\"assistant-header-actions\">\n <button\n type=\"button\"\n class=\"header-action\"\n [attr.aria-label]=\"uiCopy.clearLabel\"\n [pTooltip]=\"uiCopy.clearTooltip\"\n tooltipPosition=\"bottom\"\n (click)=\"clearChatSession()\"\n >\n <i class=\"header-action-icon pi pi-refresh\" aria-hidden=\"true\"></i>\n </button>\n <button\n type=\"button\"\n class=\"header-action\"\n [attr.aria-label]=\"uiCopy.closeLabel\"\n [pTooltip]=\"uiCopy.closeTooltip\"\n tooltipPosition=\"bottom\"\n (click)=\"requestClose()\"\n >\n <i class=\"header-action-icon pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </header>\n\n <div #messagesViewport class=\"assistant-messages\">\n @for(message of messages(); track message.id) {\n <article\n class=\"message {{ message.role }}\"\n [class.welcome-message]=\"isWelcomeMessage(message)\"\n [class.welcome]=\"isWelcomeState(message)\"\n [class.error]=\"message.isError\"\n [class.streaming]=\"message.isStreaming\"\n [attr.aria-live]=\"message.isStreaming ? 'polite' : null\"\n [attr.aria-busy]=\"message.isStreaming || null\"\n [attr.role]=\"message.isStreaming ? 'status' : null\"\n >\n @if(message.isStreaming) {\n <p class=\"streaming-progress\">{{ message.content }}</p>\n } @else if(message.displayResponse; as responseDetails) {\n @if(responseDetails.markdown || responseDetails.agentInferredResponse || message.content) {\n <div\n class=\"assistant-result assistant-markdown\"\n [innerHTML]=\"(responseDetails.markdown || responseDetails.agentInferredResponse || message.content) | maxAssistantMarkdown\"\n ></div>\n }\n @if(message.cards?.length) {\n <div class=\"assistant-cards\">\n @for(card of message.cards ?? []; track $index) {\n <section class=\"assistant-card\">\n <header>\n <span class=\"assistant-card-title\">{{ card.title }}</span>\n @if(card.subtitle) {\n <span class=\"assistant-card-subtitle\">{{ card.subtitle }}</span>\n }\n </header>\n <div class=\"assistant-card-metrics\">\n @for(metric of card.metrics; track metric.label) {\n <div class=\"assistant-card-metric\" [class.assistant-card-metric-wide]=\"isListMetric(metric)\" [attr.data-tone]=\"metric.tone || 'default'\">\n <span class=\"assistant-card-label\">{{ metric.label }}</span>\n <span class=\"assistant-card-value\">{{ metric.value }}</span>\n </div>\n }\n </div>\n @if(card.footer) {\n <footer>{{ card.footer }}</footer>\n }\n </section>\n }\n </div>\n }\n @if(responseDetails.searchResults?.length) {\n <div class=\"assistant-cards assistant-search-results\" aria-label=\"Search results\">\n @for(result of responseDetails.searchResults ?? []; track $index) {\n <section class=\"assistant-card assistant-search-result\">\n <header>\n <i\n class=\"assistant-search-result-icon\"\n [class]=\"searchResultIcon(result.type)\"\n aria-hidden=\"true\"\n ></i>\n <div class=\"assistant-search-result-copy\">\n <strong>{{ result.title }}</strong>\n <span>{{ result.type }}</span>\n </div>\n </header>\n <div class=\"suggestions\" aria-label=\"Available destinations\">\n @for(action of result.actions; track action.label) {\n <button\n pButton\n type=\"button\"\n size=\"small\"\n severity=\"secondary\"\n class=\"suggestion-chip\"\n [label]=\"action.label\"\n [icon]=\"searchActionIcon(action)\"\n [disabled]=\"isSending()\"\n (click)=\"performHostAction(action.hostAction)\"\n ></button>\n }\n </div>\n </section>\n }\n </div>\n }\n @if(message.pendingAction; as pendingAction) {\n <section class=\"pending-action\" aria-label=\"Cortex action confirmation\">\n <div class=\"pending-action-heading\">\n <strong>Confirmation required</strong>\n <span>{{ pendingAction.method }}</span>\n </div>\n <p>{{ pendingAction.summary }}</p>\n <small>Expires {{ pendingAction.expiresAt | date: 'mediumTime' }}</small>\n @if(message.actionDecision; as actionDecision) {\n <p class=\"action-decision\">\n {{ actionDecision === 'approve' ? 'Approval sent' : 'Rejection sent' }}\n </p>\n } @else {\n <div class=\"pending-action-buttons\">\n <button\n pButton\n type=\"button\"\n size=\"small\"\n severity=\"success\"\n label=\"Approve\"\n [disabled]=\"isSending()\"\n (click)=\"resolvePendingAction(message, 'approve')\"\n ></button>\n <button\n pButton\n type=\"button\"\n size=\"small\"\n outlined\n severity=\"secondary\"\n label=\"Reject\"\n [disabled]=\"isSending()\"\n (click)=\"resolvePendingAction(message, 'reject')\"\n ></button>\n </div>\n }\n </section>\n }\n @if(responseDetails.shiftCardGroups?.length) {\n <div class=\"assistant-shift-groups\" aria-label=\"Team shifts\">\n @for(group of responseDetails.shiftCardGroups ?? []; track group.title) {\n <section class=\"assistant-shift-group\">\n <h3>{{ group.title }}</h3>\n <div class=\"assistant-shift-card-grid\">\n @for(shift of group.shifts; track shift.id || $index) {\n <max-agent-shift-card\n [shift]=\"shift\"\n variant=\"definition\"\n ></max-agent-shift-card>\n }\n </div>\n </section>\n }\n </div>\n }\n @if(responseDetails.rota; as rota) {\n <section class=\"assistant-rota\" [attr.aria-label]=\"rota.title\">\n <div class=\"assistant-rota-heading\">\n <h3>{{ rota.title }}</h3>\n <div class=\"assistant-rota-summary\">\n @if(rota.startDate) {\n <span><small>From</small><strong>{{ rota.startDate }}</strong></span>\n }\n <span><small>Weeks</small><strong>{{ rota.weeksCount }}</strong></span>\n @if(rota.contracted) {\n <span><small>Contracted</small><strong>{{ rota.contracted }}</strong></span>\n }\n @if(rota.autoPublish) {\n <span><small>Auto publish</small><strong>{{ rota.autoPublish }}</strong></span>\n }\n </div>\n </div>\n <div class=\"assistant-rota-scroll\">\n @for(week of rota.weeks; track week.week) {\n <section class=\"assistant-rota-week\">\n <header class=\"assistant-rota-week-heading\">\n <strong>Week {{ week.week }}</strong>\n @if(week.duration) {\n <span>{{ week.duration }}</span>\n }\n </header>\n <div class=\"assistant-rota-week-grid\">\n @for(day of week.days; track day.day) {\n <article class=\"assistant-rota-day\">\n <header>\n <strong>{{ day.label }}</strong>\n @if(day.period) {\n <span>{{ day.period }}</span>\n }\n </header>\n <div class=\"assistant-rota-day-shifts\">\n @for(shift of day.shifts; track shift.id || $index) {\n <max-agent-shift-card\n [shift]=\"shift\"\n variant=\"rota\"\n ></max-agent-shift-card>\n } @empty {\n <span class=\"assistant-rota-empty\">No shifts</span>\n }\n </div>\n </article>\n }\n </div>\n </section>\n } @empty {\n <p class=\"assistant-rota-no-weeks\">No rota weeks were returned.</p>\n }\n </div>\n </section>\n }\n @if(responseDetails.visualisations?.length) {\n <div class=\"assistant-visualisations\">\n @for(visualisation of responseDetails.visualisations ?? []; track visualisation.title) {\n <section class=\"assistant-visualisation\">\n <header class=\"assistant-export-heading\">\n <h3>{{ visualisation.title }}</h3>\n <button\n pButton\n type=\"button\"\n size=\"small\"\n severity=\"secondary\"\n class=\"assistant-export-action assistant-export-action-pdf\"\n icon=\"pi pi-file-pdf\"\n [attr.aria-label]=\"'Export ' + visualisation.title + ' as PDF'\"\n (click)=\"exportVisualisation(visualisation)\"\n ></button>\n </header>\n @if(visualisation.type === 'doughnut') {\n <div class=\"assistant-doughnut-layout\">\n <div\n class=\"assistant-doughnut\"\n role=\"img\"\n [attr.aria-label]=\"chartAriaLabel(visualisation)\"\n >\n <svg viewBox=\"0 0 42 42\" aria-hidden=\"true\" focusable=\"false\">\n <circle\n class=\"assistant-doughnut-track\"\n cx=\"21\"\n cy=\"21\"\n r=\"15.9155\"\n ></circle>\n @for(value of visualisation.values; track $index; let valueIndex = $index) {\n <circle\n class=\"assistant-doughnut-segment\"\n cx=\"21\"\n cy=\"21\"\n r=\"15.9155\"\n pathLength=\"100\"\n [attr.stroke]=\"chartColor(visualisation, valueIndex)\"\n [attr.stroke-dasharray]=\"doughnutDashArray(visualisation, valueIndex)\"\n [attr.stroke-dashoffset]=\"doughnutDashOffset(visualisation, valueIndex)\"\n ></circle>\n }\n </svg>\n <span><strong>{{ chartTotal(visualisation) }}</strong>{{ visualisation.valueLabel || 'people' }}</span>\n </div>\n <div class=\"assistant-chart-legend\">\n @for(label of visualisation.labels; track $index; let labelIndex = $index) {\n <div class=\"assistant-chart-legend-item\">\n <i [style.background]=\"chartColor(visualisation, labelIndex)\"></i>\n <span>{{ label }}</span>\n <strong>{{ visualisation.values[labelIndex] || 0 }}</strong>\n </div>\n }\n </div>\n </div>\n } @else {\n <div\n class=\"assistant-bar-chart\"\n role=\"img\"\n [attr.aria-label]=\"chartAriaLabel(visualisation)\"\n >\n @for(label of visualisation.labels; track $index; let labelIndex = $index) {\n <div class=\"assistant-bar-row\">\n <div class=\"assistant-bar-label\">\n <span>{{ label }}</span>\n <strong>{{ visualisation.values[labelIndex] || 0 }}</strong>\n </div>\n <div class=\"assistant-bar-track\" aria-hidden=\"true\">\n <i\n [style.width.%]=\"barWidth(visualisation, labelIndex)\"\n [style.background]=\"chartColor(visualisation, labelIndex)\"\n ></i>\n </div>\n </div>\n }\n </div>\n }\n </section>\n }\n </div>\n }\n @if(getResponseGrid(responseDetails).length) {\n <div class=\"assistant-tables\">\n @for(table of getResponseGrid(responseDetails); track $index; let tableIndex = $index) {\n <section class=\"assistant-table-section\">\n <header class=\"assistant-export-heading\">\n @if(table.title) {\n <h3>{{ table.title }}</h3>\n }\n <button\n pButton\n type=\"button\"\n size=\"small\"\n severity=\"secondary\"\n class=\"assistant-export-action assistant-export-action-excel\"\n icon=\"pi pi-file-excel\"\n [attr.aria-label]=\"'Export ' + (table.title || 'results') + ' to Excel'\"\n (click)=\"exportTable(table)\"\n ></button>\n </header>\n <div class=\"assistant-table-wrap\">\n <table>\n <thead>\n <tr>\n @if(table.pagination) {\n <th>SL. No</th>\n }\n @for(column of table.columns; track column.field) {\n <th>{{ column.header }}</th>\n }\n @if(table.actions?.length) {\n <th>Actions</th>\n }\n </tr>\n </thead>\n <tbody>\n @for(row of table.rows; track $index; let rowIndex = $index) {\n <tr>\n @if(table.pagination) {\n <td>{{ rowIndex + 1 }}</td>\n }\n @for(column of table.columns; track column.field) {\n <td>{{ row[column.field] }}</td>\n }\n @if(table.actions?.length) {\n <td>\n <div class=\"assistant-table-actions\">\n @for(action of getTableRowActions(table, rowIndex); track action.label) {\n <button\n pButton\n type=\"button\"\n size=\"small\"\n [severity]=\"action.tone || 'secondary'\"\n [outlined]=\"action.tone === 'danger'\"\n [label]=\"action.label\"\n [disabled]=\"isSending()\"\n (click)=\"useTableAction(action)\"\n ></button>\n }\n </div>\n </td>\n }\n </tr>\n }\n </tbody>\n </table>\n </div>\n @if(table.pagination; as pagination) {\n <footer class=\"assistant-table-pagination\">\n <span>{{ tablePageStatus(table) }}</span>\n @if(hasNextTablePage(table)) {\n <button\n pButton\n type=\"button\"\n size=\"small\"\n severity=\"secondary\"\n class=\"assistant-table-page-action\"\n icon=\"pi pi-arrow-down\"\n [label]=\"nextTablePageLabel(pagination)\"\n [loading]=\"isTablePageLoading(message.id, tableIndex)\"\n [disabled]=\"isSending()\"\n (click)=\"retrieveNextTablePage(message, table, tableIndex)\"\n ></button>\n }\n </footer>\n @if(tablePageError(message.id, tableIndex); as pageError) {\n <p class=\"assistant-table-page-error\" role=\"alert\">{{ pageError }}</p>\n }\n }\n </section>\n }\n </div>\n }\n @if(message.sources?.length) {\n <div class=\"assistant-sources\">\n <strong>Sources</strong>\n @for(source of message.sources ?? []; track source.citation) {\n <span>{{ source.citation }}</span>\n }\n </div>\n }\n @if(developerDetailsEnabled && message.developerTrace?.steps?.length) {\n @if(isDetailsVisible(message.id)) {\n <div class=\"details-dialog-backdrop\" (click)=\"toggleDetails(message.id)\">\n <section\n class=\"developer-details\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"Agent processing details\"\n (click)=\"$event.stopPropagation()\"\n >\n <header class=\"developer-details-header\">\n <div>\n <span class=\"developer-eyebrow\">Developer trace</span>\n <h3>How this request was processed</h3>\n <p>A technical, step-by-step account of routing, inference, tools and results.</p>\n </div>\n <div class=\"details-dialog-actions\">\n <button\n type=\"button\"\n class=\"details-dialog-close\"\n aria-label=\"Close processing details\"\n (click)=\"toggleDetails(message.id)\"\n >\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </header>\n\n @if(message.developerTrace!.run; as run) {\n <section class=\"trace-run-summary\" aria-label=\"Run summary\">\n <div class=\"trace-metric\"><span>Total runtime</span><strong>{{ run.durationMs }} ms</strong></div>\n <div class=\"trace-metric\"><span>Model calls</span><strong>{{ run.llmCalls }}</strong></div>\n <div class=\"trace-metric\"><span>Embedding calls</span><strong>{{ run.embeddingCalls }}</strong></div>\n <div class=\"trace-metric\"><span>API calls</span><strong>{{ run.apiCalls }}</strong></div>\n <div class=\"trace-loop-policy\">\n <div>\n <span>Execution architecture</span>\n <strong>Deterministic step pipeline</strong>\n </div>\n <span class=\"trace-no-loop\">No autonomous model loop</span>\n <p>{{ run.loopPolicy }}</p>\n </div>\n </section>\n }\n\n <ol class=\"workflow-trace\">\n @for(step of message.developerTrace!.steps; track step.id; let stepIndex = $index) {\n <li class=\"workflow-step\" [attr.data-status]=\"traceStepTone(step)\">\n <section class=\"workflow-section\">\n <button\n type=\"button\"\n class=\"workflow-step-toggle\"\n [attr.aria-expanded]=\"isTraceStepExpanded(message.id, step.id)\"\n (click)=\"toggleTraceStep(message.id, step.id)\"\n >\n <div>\n <span class=\"workflow-step-number\">Step {{ stepIndex + 1 }}</span>\n <h4>{{ step.title }}</h4>\n <span class=\"workflow-category\">{{ formatTraceCategory(step.category) }}</span>\n </div>\n <div class=\"workflow-meta\">\n <span class=\"workflow-status\">{{ traceStepStatus(step) }}</span>\n @if(step.durationMs !== undefined) {\n <span>{{ step.durationMs }} ms</span>\n }\n <i\n class=\"pi workflow-expand-icon\"\n [class.pi-chevron-down]=\"isTraceStepExpanded(message.id, step.id)\"\n [class.pi-chevron-right]=\"!isTraceStepExpanded(message.id, step.id)\"\n aria-hidden=\"true\"\n ></i>\n </div>\n </button>\n\n @if(isTraceStepExpanded(message.id, step.id)) {\n <div class=\"workflow-step-content\">\n @if(step.metadata?.summary) {\n <p class=\"workflow-summary\">{{ step.metadata!.summary }}</p>\n }\n\n @if(step.metadata?.technology; as technology) {\n <div class=\"trace-technology\">\n <span class=\"trace-section-label\">Technology</span>\n <div class=\"trace-inline-facts\">\n <span><small>Component</small>{{ technology.component }}</span>\n @if(technology.model) { <span><small>Model</small>{{ technology.model }}</span> }\n @if(technology.library) { <span><small>Library</small>{{ technology.library }}</span> }\n @if(technology.provider) { <span><small>Provider</small>{{ technology.provider }}</span> }\n @if(technology.operation) { <span><small>Operation</small>{{ technology.operation }}</span> }\n </div>\n </div>\n }\n\n @if(step.metadata?.control; as control) {\n <div class=\"trace-control\">\n <div>\n <span class=\"trace-section-label\">Stop control</span>\n <strong>{{ formatTraceLabel(control.mode) }}</strong>\n </div>\n @if(control.maximumIterations !== undefined) {\n <span>{{ control.iterationsUsed ?? 0 }} / {{ control.maximumIterations }} iteration</span>\n }\n <p>{{ control.stopCondition }}</p>\n </div>\n }\n\n @switch(step.category) {\n @case('request') {\n @if(traceField(step.input, 'userQuery'); as userQuery) {\n <div class=\"trace-query\">\n <span>Original user query</span>\n <blockquote>{{ formatTraceScalar(userQuery) }}</blockquote>\n </div>\n }\n <div class=\"trace-card-grid\">\n @for(group of [\n { label: 'Product', value: traceMapField(step.input, 'product') },\n { label: 'User', value: traceMapField(step.input, 'user') },\n { label: 'Request context', value: traceMapField(step.input, 'requestContext') },\n { label: 'Conversation', value: traceMapField(step.input, 'conversation') },\n { label: 'Live API context', value: traceMapField(step.input, 'liveApi') }\n ]; track group.label) {\n @if(group.value) {\n <section class=\"trace-data-card\">\n <h5>{{ group.label }}</h5>\n <dl class=\"trace-field-list\">\n @for(entry of traceEntries(group.value, group.label === 'User' ? ['permissions'] : []); track entry.key) {\n <div><dt>{{ entry.label }}</dt><dd>{{ formatTraceScalar(entry.value) }}</dd></div>\n }\n </dl>\n </section>\n }\n }\n </div>\n }\n\n @case('intent_projection') {\n <div class=\"trace-transform\">\n <div>\n <span>Original query</span>\n <p>{{ formatTraceScalar(traceField(step.output, 'originalUserQuery') ?? traceField(step.input, 'originalUserQuery')) }}</p>\n </div>\n <span class=\"trace-transform-arrow\" aria-hidden=\"true\">\u2192</span>\n <div class=\"trace-transform-result\">\n <span>Generalised intent sent to embedding</span>\n <p>{{ formatTraceScalar(traceField(step.output, 'generalisedIntent') ?? traceField(step.output, 'routingText')) }}</p>\n </div>\n </div>\n @if(traceArrayField(step.output, 'removedArguments').length) {\n <div class=\"trace-section\">\n <span class=\"trace-section-label\">Arguments removed before routing</span>\n <div class=\"trace-entity-list\">\n @for(argument of traceArrayField(step.output, 'removedArguments'); track $index) {\n <span><small>{{ formatTraceScalar(traceField(argument, 'kind')) }}</small>{{ formatTraceScalar(traceField(argument, 'value')) }}</span>\n }\n </div>\n </div>\n }\n }\n\n @case('embedding') {\n <div class=\"trace-query trace-query-compact\">\n <span>Embedded text</span>\n <blockquote>{{ formatTraceScalar(traceField(step.input, 'generalisedIntent')) }}</blockquote>\n </div>\n <div class=\"trace-stat-grid\">\n <div><span>Embedding model</span><strong>{{ formatTraceScalar(traceField(step.output, 'model') ?? traceField(step.input, 'model')) }}</strong></div>\n <div><span>Dimensions</span><strong>{{ formatTraceScalar(traceField(step.output, 'dimensions')) }}</strong></div>\n <div><span>Vector magnitude</span><strong>{{ formatTraceScalar(traceField(step.output, 'vectorMagnitude')) }}</strong></div>\n <div><span>Full vector exposed</span><strong>{{ formatTraceScalar(traceField(step.output, 'fullVectorShown')) }}</strong></div>\n </div>\n @if(traceField(step.output, 'vectorPreview'); as vectorPreview) {\n <div class=\"trace-vector\">\n <span>Vector preview</span>\n <code>{{ formatTraceScalar(vectorPreview) }}</code>\n </div>\n }\n }\n\n @case('capability_routing') {\n @if(traceMapField(step.output, 'routing'); as routing) {\n <div class=\"trace-supabase-call\">\n <div><span>Routing strategy</span><strong>{{ formatTraceScalar(traceField(routing, 'strategy')) }}</strong></div>\n <div><span>Cache status</span><strong>{{ formatTraceScalar(traceField(routing, 'cacheStatus')) }}</strong></div>\n <div><span>Supabase RPC executed</span><strong>{{ formatTraceScalar(traceField(routing, 'supabaseRpcExecuted')) }}</strong></div>\n <div><span>Vector search executed</span><strong>{{ formatTraceScalar(traceField(routing, 'vectorSearchExecuted')) }}</strong></div>\n @if(traceField(routing, 'supabaseRpcExecuted')) {\n <div><span>Supabase RPC</span><strong>{{ formatTraceScalar(traceField(routing, 'rpc')) }}</strong></div>\n <div><span>Database</span><strong>{{ formatTraceScalar(traceField(routing, 'database')) }}</strong></div>\n @if(traceArrayField(routing, 'tables').length) {\n <div class=\"trace-table-list\">\n <span>Tables searched</span>\n <div>\n @for(table of traceArrayField(routing, 'tables'); track $index) {\n <code>{{ formatTraceScalar(table) }}</code>\n }\n </div>\n </div>\n }\n }\n </div>\n } @else {\n <div class=\"trace-supabase-call\">\n <div><span>Supabase RPC</span><strong>{{ formatTraceScalar(traceField(step.input, 'rpc')) }}</strong></div>\n <div><span>Database</span><strong>{{ formatTraceScalar(traceField(step.input, 'database')) }}</strong></div>\n @if(traceArrayField(step.input, 'tables').length) {\n <div class=\"trace-table-list\">\n <span>Tables searched</span>\n <div>\n @for(table of traceArrayField(step.input, 'tables'); track $index) {\n <code>{{ formatTraceScalar(table) }}</code>\n }\n </div>\n </div>\n }\n </div>\n }\n @if(traceMapField(step.output, 'decision'); as decision) {\n <section class=\"trace-decision\">\n <span>Routing decision</span>\n <strong>{{ formatTraceScalar(decision['selectedCapabilityLabel'] ?? decision['selectedCapabilityKey']) }}</strong>\n <div>\n <span>Status: {{ formatTraceScalar(decision['status']) }}</span>\n <span>Confidence: {{ formatSimilarity(decision['confidence']) }}</span>\n <span>Runner-up: {{ formatSimilarity(decision['runnerUpConfidence']) }}</span>\n </div>\n </section>\n }\n @if(traceArrayField(step.output, 'matchedCapabilities').length) {\n <div class=\"trace-ranking-wrap\">\n <span class=\"trace-section-label\">Ranked capability matches</span>\n <table class=\"trace-ranking\">\n <thead><tr><th>#</th><th>Capability</th><th>Combined</th><th>Semantic</th><th>Definition</th><th>Example</th><th>Keyword</th></tr></thead>\n <tbody>\n @for(candidate of traceArrayField(step.output, 'matchedCapabilities'); track $index) {\n <tr>\n <td>{{ formatTraceScalar(traceField(candidate, 'rank')) }}</td>\n <td><strong>{{ formatTraceScalar(traceField(candidate, 'label')) }}</strong><code>{{ formatTraceScalar(traceField(candidate, 'capabilityKey')) }}</code></td>\n <td>{{ formatSimilarity(traceField(candidate, 'combinedScore')) }}</td>\n <td>{{ formatSimilarity(traceField(candidate, 'semanticScore')) }}</td>\n <td>{{ formatSimilarity(traceField(candidate, 'definitionScore')) }}</td>\n <td>{{ formatSimilarity(traceField(candidate, 'exampleScore')) }}</td>\n <td>{{ formatSimilarity(traceField(candidate, 'keywordScore')) }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n }\n\n @case('argument_extraction') {\n <div class=\"trace-card-grid\">\n @if(traceMapField(step.output, 'selectedCapability') ?? traceMapField(step.input, 'selectedCapability'); as capability) {\n <section class=\"trace-data-card trace-data-card-accent\">\n <h5>Selected capability</h5>\n <dl class=\"trace-field-list\">\n @for(entry of traceEntries(capability); track entry.key) {\n <div><dt>{{ entry.label }}</dt><dd>{{ formatTraceScalar(entry.value) }}</dd></div>\n }\n </dl>\n </section>\n }\n @if(traceMapField(step.input, 'tool'); as tool) {\n <section class=\"trace-data-card\">\n <h5>Allowlisted tool</h5>\n <dl class=\"trace-field-list\">\n @for(entry of traceEntries(tool); track entry.key) {\n <div><dt>{{ entry.label }}</dt><dd>{{ formatTraceScalar(entry.value) }}</dd></div>\n }\n </dl>\n </section>\n }\n </div>\n @if(traceMapField(step.output, 'extractedArguments'); as arguments) {\n <section class=\"trace-arguments\">\n <span class=\"trace-section-label\">Arguments extracted from the original query</span>\n <dl class=\"trace-argument-grid\">\n @for(entry of traceEntries(arguments); track entry.key) {\n <div><dt>{{ entry.label }}</dt><dd>{{ formatTraceScalar(entry.value) }}</dd></div>\n }\n </dl>\n </section>\n }\n @if(traceMapField(step.output, 'plannedToolCall'); as plannedCall) {\n <div class=\"trace-tool-call\">\n <span>Planned tool call</span>\n <strong>{{ formatTraceScalar(plannedCall['method']) }} \u00B7 {{ formatTraceScalar(plannedCall['toolName']) }}</strong>\n <pre>{{ formatTraceValue(plannedCall['arguments']) }}</pre>\n </div>\n }\n }\n\n @case('api_call') {\n @if(traceField(step.input, 'sql'); as sql) {\n <div class=\"trace-tool-call trace-sql-query\">\n <span>SQL sent to MySQL MCP</span>\n <strong>{{ formatTraceScalar(traceField(step.input, 'toolName')) }}</strong>\n <pre>{{ formatTraceScalar(sql) }}</pre>\n </div>\n }\n @if(traceField(step.input, 'method') || traceField(step.input, 'path')) {\n <div class=\"trace-api-route\">\n <span class=\"trace-http-method\">{{ formatTraceScalar(traceField(step.input, 'method')) }}</span>\n <code>{{ formatTraceScalar(traceField(step.input, 'path')) }}</code>\n @if(getHttpStatus(step); as statusCode) {\n <span class=\"trace-http-status\" [class.success]=\"isHttpSuccessful(step)\" [class.error]=\"!isHttpSuccessful(step)\">\n HTTP {{ statusCode }} \u00B7 {{ isHttpSuccessful(step) ? 'Success' : 'Error' }}\n </span>\n }\n </div>\n }\n <div class=\"trace-payload-grid\">\n @if(traceField(step.input, 'body'); as requestBody) {\n <section><span>Request payload</span><pre>{{ formatTraceValue(requestBody) }}</pre></section>\n }\n @if(traceField(step.output, 'response'); as apiResponse) {\n <section><span>API response</span><pre>{{ formatTraceValue(apiResponse) }}</pre></section>\n }\n @if(traceField(step.input, 'sql') && step.output !== undefined) {\n <section><span>MySQL MCP execution details</span><pre>{{ formatTraceValue(step.output) }}</pre></section>\n }\n </div>\n }\n\n @case('action') {\n <div class=\"trace-card-grid\">\n <section class=\"trace-data-card\">\n <h5>Workflow input</h5>\n <dl class=\"trace-field-list\">\n @for(entry of traceEntries(step.input); track entry.key) {\n <div><dt>{{ entry.label }}</dt><dd>{{ formatTraceScalar(entry.value) }}</dd></div>\n }\n </dl>\n </section>\n <section class=\"trace-data-card trace-data-card-accent\">\n <h5>Outcome</h5>\n <dl class=\"trace-field-list\">\n @for(entry of traceEntries(step.output); track entry.key) {\n <div><dt>{{ entry.label }}</dt><dd>{{ formatTraceScalar(entry.value) }}</dd></div>\n }\n </dl>\n </section>\n </div>\n }\n\n @case('response') {\n @if(traceField(step.output, 'answer'); as answer) {\n <div class=\"trace-query\"><span>Final grounded response</span><blockquote>{{ formatTraceScalar(answer) }}</blockquote></div>\n }\n <dl class=\"trace-argument-grid\">\n @for(entry of traceEntries(step.output); track entry.key) {\n @if(entry.key !== 'answer') {\n <div><dt>{{ entry.label }}</dt><dd>{{ formatTraceScalar(entry.value) }}</dd></div>\n }\n }\n </dl>\n }\n\n @default {\n <div class=\"trace-payload-grid\">\n @if(step.input !== undefined) {\n <section><span>Input</span><pre>{{ formatTraceValue(step.input) }}</pre></section>\n }\n @if(step.output !== undefined) {\n <section><span>Output</span><pre>{{ formatTraceValue(step.output) }}</pre></section>\n }\n </div>\n }\n }\n\n @if(step.error; as error) {\n <div class=\"trace-error\" [class.trace-warning]=\"step.category === 'api_call' && isHttpSuccessful(step)\">\n <strong class=\"trace-error-heading\">\n @if(step.category === 'api_call' && isHttpSuccessful(step)) {\n Post-response processing stopped\n } @else {\n Step stopped@if(error.statusCode) { \u00B7 HTTP {{ error.statusCode }} }\n }\n </strong>\n <strong class=\"trace-error-legacy\" aria-hidden=\"true\">\n Failed@if(error.statusCode) { \u2014 HTTP {{ error.statusCode }} }\n </strong>\n <span>{{ error.message }}</span>\n </div>\n }\n </div>\n }\n </section>\n </li>\n }\n </ol>\n </section>\n </div>\n }\n }\n } @else {\n @if(message.role === 'assistant') {\n <div\n class=\"assistant-markdown\"\n [innerHTML]=\"message.content | maxAssistantMarkdown\"\n ></div>\n @if(isWelcomeState(message) && bootstrapConfig.initialDescription; as initialDescription) {\n <p class=\"welcome-description\">{{ initialDescription }}</p>\n }\n @if(isWelcomeState(message)) {\n <button\n type=\"button\"\n class=\"support-welcome-card\"\n aria-label=\"Raise a support ticket\"\n (click)=\"openSupportTicket()\"\n >\n <span class=\"support-welcome-icon\" aria-hidden=\"true\">\n <i class=\"far fa-user-headset\"></i>\n </span>\n <span class=\"support-welcome-copy\">\n <strong>Raise a support ticket</strong>\n <small>Send details directly to our support team.</small>\n </span>\n <i class=\"support-welcome-arrow pi pi-arrow-right\" aria-hidden=\"true\"></i>\n </button>\n }\n } @else {\n <p>{{ message.content }}</p>\n }\n }\n @if(message.role === 'assistant' && message.suggestions?.length) {\n @if(hasCapabilitySuggestions(message.suggestions)) {\n <div class=\"capability-options\" aria-label=\"Available Maxtime capabilities\">\n @for(group of capabilitySuggestionGroups(message.suggestions); track group.section) {\n <section class=\"capability-option-section\">\n <h3>{{ group.section }}</h3>\n <div class=\"capability-option-grid\">\n @for(suggestion of group.options; track suggestion.structuredAction?.capabilityKey ?? suggestion.label; let optionIndex = $index) {\n <button\n pButton\n type=\"button\"\n severity=\"secondary\"\n class=\"capability-option-card\"\n [disabled]=\"isSending()\"\n [attr.aria-label]=\"'Choose capability: ' + suggestion.label\"\n (click)=\"useSuggestion(suggestion)\"\n >\n <span class=\"capability-option-number\" aria-hidden=\"true\">\n {{ optionIndex + 1 }}\n </span>\n <span class=\"capability-option-copy\">{{ suggestion.label }}</span>\n <i class=\"pi pi-arrow-right capability-option-arrow\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n </section>\n }\n </div>\n } @else if(hasOptionCardSuggestions(message.suggestions, message.status)) {\n <div class=\"clarification-options\" aria-label=\"Clarification options\">\n <div class=\"capability-option-grid clarification-option-grid\">\n @for(suggestion of optionCardSuggestions(message.suggestions, message.status); track suggestionLabel(suggestion); let optionIndex = $index) {\n <button\n pButton\n type=\"button\"\n severity=\"secondary\"\n class=\"capability-option-card clarification-option-card\"\n [disabled]=\"isSending()\"\n [attr.aria-label]=\"'Choose option: ' + suggestionLabel(suggestion)\"\n (click)=\"useSuggestion(suggestion)\"\n >\n <span class=\"capability-option-number\" aria-hidden=\"true\">\n {{ optionIndex + 1 }}\n </span>\n <span class=\"capability-option-copy\">{{ suggestionLabel(suggestion) }}</span>\n <i class=\"pi pi-arrow-right capability-option-arrow\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n </div>\n } @else if(hasEntitySuggestions(message.suggestions)) {\n <div class=\"entity-options\" aria-label=\"Matching options\">\n @for(suggestion of entitySuggestionOptions(message.suggestions); track suggestion.entity.id ?? suggestion.label) {\n <max-agent-entity-option\n [entity]=\"suggestion.entity\"\n [disabled]=\"isSending()\"\n (selected)=\"useSuggestion(suggestion)\"\n ></max-agent-entity-option>\n }\n </div>\n } @else {\n <div class=\"suggestions\">\n @for(suggestion of message.suggestions ?? []; track suggestion) {\n <button\n pButton\n type=\"button\"\n size=\"small\"\n text\n severity=\"secondary\"\n class=\"suggestion-chip\"\n [label]=\"suggestionLabel(suggestion)\"\n (click)=\"useSuggestion(suggestion)\"\n ></button>\n }\n </div>\n }\n }\n @if(message.role === 'assistant' && !isWelcomeMessage(message) && !message.isStreaming) {\n <div class=\"response-actions\">\n <button\n type=\"button\"\n class=\"response-feedback-action\"\n [attr.aria-label]=\"uiCopy.feedbackLabel\"\n [pTooltip]=\"uiCopy.feedbackTooltip\"\n tooltipPosition=\"bottom\"\n (click)=\"openFeedback(message)\"\n >\n <i class=\"pi pi-comment\" aria-hidden=\"true\"></i>\n </button>\n @if(developerDetailsEnabled && message.developerTrace?.steps?.length) {\n <button\n type=\"button\"\n class=\"details-toggle\"\n [attr.aria-expanded]=\"isDetailsVisible(message.id)\"\n (click)=\"toggleDetails(message.id, message.developerTrace!.steps[0]?.id)\"\n >\n {{ isDetailsVisible(message.id) ? 'Hide Developer Trace' : 'Show Developer Trace' }}\n </button>\n }\n </div>\n }\n </article>\n }\n </div>\n\n <footer class=\"assistant-footer\">\n @if(hasConversationStarted()) {\n <button\n type=\"button\"\n class=\"support-ticket-shortcut\"\n aria-label=\"Raise a support ticket\"\n (click)=\"openSupportTicket()\"\n >\n <i class=\"far fa-user-headset\" aria-hidden=\"true\"></i>\n <span>Raise a support ticket</span>\n </button>\n }\n <form class=\"assistant-composer\" (ngSubmit)=\"sendMessage()\">\n <textarea\n #composerInput\n pTextarea\n name=\"assistantPrompt\"\n rows=\"1\"\n [placeholder]=\"uiCopy.placeholder\"\n [ngModel]=\"input()\"\n (ngModelChange)=\"input.set($event)\"\n (keydown)=\"onComposerKeydown($event)\"\n >\n </textarea>\n <button\n pButton\n type=\"submit\"\n icon=\"pi pi-send\"\n aria-label=\"Send message\"\n [disabled]=\"!input().trim() || isSending()\"\n ></button>\n </form>\n </footer>\n </section>\n\n @if(supportTicketVisible()) {\n <section class=\"support-ticket-overlay\" aria-label=\"Support ticket form\">\n <div\n class=\"support-ticket-dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"supportTicketTitle\"\n >\n <header class=\"support-ticket-header\">\n <span class=\"support-ticket-header-icon\" aria-hidden=\"true\">\n <i class=\"far fa-user-headset\"></i>\n </span>\n <div>\n <h2 id=\"supportTicketTitle\">Raise a support ticket</h2>\n <p>Share the details and our support team will take it from here.</p>\n </div>\n <button\n type=\"button\"\n class=\"support-ticket-close\"\n aria-label=\"Close support ticket form\"\n (click)=\"closeSupportTicket()\"\n >\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </header>\n\n @if(supportTicketSubmissionFailed()) {\n <div class=\"support-ticket-error-page\" role=\"alert\">\n <span class=\"support-ticket-error-icon\" aria-hidden=\"true\">\n <i class=\"pi pi-times-circle\"></i>\n </span>\n <h3>Ticket could not be created</h3>\n <p>{{ supportTicketError() }}</p>\n <button\n pButton\n type=\"button\"\n label=\"Close\"\n icon=\"pi pi-times\"\n severity=\"secondary\"\n (click)=\"closeSupportTicket()\"\n ></button>\n </div>\n } @else if(supportTicketResult(); as result) {\n <div class=\"support-ticket-success\" role=\"status\">\n <span class=\"support-ticket-success-icon\" aria-hidden=\"true\">\n <i class=\"pi pi-check\"></i>\n </span>\n <h3>Ticket raised</h3>\n <p>{{ result.message }}</p>\n @if(result.ticketReference) {\n <div class=\"support-ticket-reference\">\n <span>Reference</span>\n <strong>{{ result.ticketReference }}</strong>\n </div>\n }\n <button\n pButton\n type=\"button\"\n label=\"Done\"\n icon=\"pi pi-check\"\n (click)=\"closeSupportTicket()\"\n ></button>\n </div>\n } @else {\n <form class=\"support-ticket-form\" (ngSubmit)=\"submitSupportTicket()\">\n <div class=\"support-ticket-fields\">\n <label class=\"support-ticket-field\">\n <span>Name</span>\n <input\n type=\"text\"\n name=\"supportName\"\n autocomplete=\"name\"\n [value]=\"supportTicketForm.name\"\n readonly\n />\n </label>\n\n <label class=\"support-ticket-field\">\n <span>Email</span>\n <input\n type=\"email\"\n name=\"supportEmail\"\n autocomplete=\"email\"\n [value]=\"supportTicketForm.email\"\n readonly\n />\n </label>\n\n <label class=\"support-ticket-field support-ticket-field-wide\">\n <span>Phone <small>Optional</small></span>\n <input\n type=\"tel\"\n name=\"supportPhone\"\n autocomplete=\"tel\"\n placeholder=\"Add a contact number\"\n [(ngModel)]=\"supportTicketForm.phone\"\n />\n </label>\n\n <label class=\"support-ticket-field\">\n <span>Severity</span>\n <p-select\n inputId=\"supportSeverity\"\n name=\"supportSeverity\"\n [options]=\"supportSeverities()\"\n optionLabel=\"label\"\n [fluid]=\"true\"\n [loading]=\"supportSeverities().length === 0\"\n [(ngModel)]=\"supportTicketForm.severity\"\n >\n <ng-template #selectedItem let-severity>\n <p-tag\n class=\"support-severity-tag\"\n [value]=\"severity.label\"\n [style.--support-severity-color]=\"supportSeverityColor(severity.color)\"\n [rounded]=\"true\"\n ></p-tag>\n </ng-template>\n <ng-template #item let-severity>\n <p-tag\n class=\"support-severity-option\"\n [value]=\"severity.label\"\n [style.--support-severity-color]=\"supportSeverityColor(severity.color)\"\n [rounded]=\"true\"\n ></p-tag>\n </ng-template>\n </p-select>\n </label>\n\n <label class=\"support-ticket-field\">\n <span>Tags</span>\n <p-multiselect\n inputId=\"supportTags\"\n name=\"supportTags\"\n placeholder=\"Select relevant areas\"\n [options]=\"supportTags()\"\n optionLabel=\"label\"\n dataKey=\"id\"\n display=\"chip\"\n [filter]=\"true\"\n filterBy=\"label\"\n [showToggleAll]=\"false\"\n [loading]=\"supportTagsLoading()\"\n [fluid]=\"true\"\n [(ngModel)]=\"supportTicketForm.tags\"\n >\n <ng-template #selecteditems let-selectedTags>\n <span class=\"support-selected-tags\">\n @for(tag of selectedTags; track tag.id) {\n <p-tag\n class=\"support-selected-tag\"\n [value]=\"tag.label\"\n [icon]=\"tag.icon\"\n [severity]=\"tag.severity\"\n [rounded]=\"true\"\n ></p-tag>\n }\n </span>\n </ng-template>\n <ng-template #item let-tag>\n <p-tag\n class=\"support-tag-option\"\n [value]=\"tag.label\"\n [icon]=\"tag.icon\"\n [severity]=\"tag.severity\"\n [rounded]=\"true\"\n ></p-tag>\n </ng-template>\n </p-multiselect>\n </label>\n\n <label class=\"support-ticket-field support-ticket-field-wide\">\n <span>Subject</span>\n <input\n type=\"text\"\n name=\"supportSubject\"\n maxlength=\"200\"\n placeholder=\"Summarise the issue\"\n required\n [(ngModel)]=\"supportTicketForm.subject\"\n />\n </label>\n\n <label class=\"support-ticket-field support-ticket-field-wide\">\n <span>How can we help?</span>\n <textarea\n #supportQueryInput\n pTextarea\n name=\"supportQuery\"\n rows=\"5\"\n placeholder=\"Describe the issue, what you expected, and anything you've already tried.\"\n required\n [(ngModel)]=\"supportTicketForm.query\"\n ></textarea>\n </label>\n </div>\n\n @if(!supportTicketForm.name || !supportTicketForm.email) {\n <p class=\"support-ticket-notice\" role=\"alert\">\n Your signed-in name and email are required. Please refresh your Nemesys session and try again.\n </p>\n }\n @if(supportTicketError(); as supportError) {\n <p class=\"support-ticket-error\" role=\"alert\">{{ supportError }}</p>\n }\n\n <div class=\"support-ticket-actions\">\n <button\n pButton\n type=\"button\"\n label=\"Cancel\"\n severity=\"secondary\"\n outlined\n (click)=\"closeSupportTicket()\"\n ></button>\n <button\n pButton\n type=\"submit\"\n label=\"Submit ticket\"\n icon=\"pi pi-send\"\n [loading]=\"supportTicketSubmitting()\"\n [disabled]=\"!canSubmitSupportTicket()\"\n ></button>\n </div>\n </form>\n }\n </div>\n </section>\n }\n\n @if(feedbackVisible()) {\n <section\n class=\"support-ticket-overlay feedback-overlay\"\n aria-label=\"Feedback form\"\n >\n <div\n class=\"support-ticket-dialog feedback-dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"feedbackTitle\"\n >\n <header class=\"support-ticket-header feedback-header\">\n <span class=\"support-ticket-header-icon\" aria-hidden=\"true\">\n <i class=\"pi pi-comment\"></i>\n </span>\n <div>\n <h2 id=\"feedbackTitle\">Help Max improve</h2>\n <p>Tell us what Max could do better.</p>\n </div>\n <button\n type=\"button\"\n class=\"support-ticket-close feedback-close\"\n aria-label=\"Close feedback form\"\n (click)=\"closeFeedback()\"\n >\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </header>\n\n @if(feedbackResult(); as result) {\n <div class=\"support-ticket-success feedback-success\" role=\"status\">\n <span class=\"support-ticket-success-icon\" aria-hidden=\"true\">\n <i class=\"pi pi-check\"></i>\n </span>\n <h3>Feedback received</h3>\n <p>{{ result.message }}</p>\n <div class=\"support-ticket-reference\">\n <span>Reference</span>\n <strong>{{ result.feedbackReference }}</strong>\n </div>\n <button\n pButton\n type=\"button\"\n label=\"Done\"\n icon=\"pi pi-check\"\n (click)=\"closeFeedback()\"\n ></button>\n </div>\n } @else {\n <form class=\"support-ticket-form feedback-form\" (ngSubmit)=\"submitFeedback()\">\n <div class=\"feedback-form-body\">\n <div class=\"support-ticket-fields\">\n <label class=\"support-ticket-field\">\n <span>Name</span>\n <input\n type=\"text\"\n name=\"feedbackName\"\n autocomplete=\"name\"\n [value]=\"feedbackForm.name\"\n readonly\n />\n </label>\n\n <label class=\"support-ticket-field\">\n <span>Email</span>\n <input\n type=\"email\"\n name=\"feedbackEmail\"\n autocomplete=\"email\"\n [value]=\"feedbackForm.email\"\n readonly\n />\n </label>\n\n <label class=\"support-ticket-field\">\n <span>Phone <small>Optional</small></span>\n <input\n type=\"tel\"\n name=\"feedbackPhone\"\n autocomplete=\"tel\"\n placeholder=\"Add a contact number\"\n [(ngModel)]=\"feedbackForm.phone\"\n />\n </label>\n\n <label class=\"support-ticket-field\">\n <span>Feedback type</span>\n <p-select\n inputId=\"feedbackCategory\"\n name=\"feedbackCategory\"\n [options]=\"feedbackCategoryOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [fluid]=\"true\"\n [(ngModel)]=\"feedbackForm.category\"\n ></p-select>\n </label>\n\n <label class=\"support-ticket-field support-ticket-field-wide\">\n <span>Your query</span>\n <textarea\n pTextarea\n name=\"feedbackQuery\"\n rows=\"2\"\n placeholder=\"Enter the question or request you gave Max.\"\n readonly\n required\n [(ngModel)]=\"feedbackForm.query\"\n ></textarea>\n </label>\n\n <label class=\"support-ticket-field support-ticket-field-wide\">\n <span>Assistant response <small>Added automatically when available</small></span>\n <textarea\n pTextarea\n name=\"feedbackAssistantResponse\"\n rows=\"3\"\n placeholder=\"No assistant response is available yet.\"\n [value]=\"feedbackForm.assistantResponse\"\n readonly\n ></textarea>\n </label>\n\n <label class=\"support-ticket-field support-ticket-field-wide\">\n <span>What could be improved?</span>\n <textarea\n #feedbackInput\n pTextarea\n name=\"feedbackDetails\"\n rows=\"3\"\n placeholder=\"Tell us what you expected, what was missing, or how the response could be more useful.\"\n required\n [(ngModel)]=\"feedbackForm.feedback\"\n ></textarea>\n </label>\n </div>\n\n @if(!feedbackForm.name || !feedbackForm.email) {\n <p class=\"support-ticket-notice\" role=\"alert\">\n Your signed-in name and email are required. Please refresh your Nemesys session and try again.\n </p>\n }\n @if(feedbackError(); as error) {\n <p class=\"support-ticket-error\" role=\"alert\">{{ error }}</p>\n }\n </div>\n\n <footer class=\"support-ticket-actions feedback-actions\">\n <button\n pButton\n type=\"button\"\n label=\"Cancel\"\n severity=\"secondary\"\n outlined\n (click)=\"closeFeedback()\"\n ></button>\n <button\n pButton\n type=\"submit\"\n label=\"Send feedback\"\n icon=\"pi pi-send\"\n [loading]=\"feedbackSubmitting()\"\n [disabled]=\"!canSubmitFeedback()\"\n ></button>\n </footer>\n </form>\n }\n </div>\n </section>\n }\n</aside>\n", styles: [":host{position:relative;display:block;width:100%;height:100%;min-height:0}.assistant-launcher{position:relative;width:64px!important;height:64px!important;min-height:64px!important;padding:7px;border:1px solid rgba(124,58,237,.24)!important;border-radius:22px!important;color:inherit!important;background:radial-gradient(circle at 28% 16%,rgba(255,255,255,.98),transparent 38%),linear-gradient(145deg,#fff7ed,#f5f3ff 52%,#fdf2f8)!important;box-shadow:0 0 0 1px #ffffffd9 inset,0 12px 30px #5b21b62e!important;overflow:visible;transition:border-color .22s ease,box-shadow .22s ease,transform .22s cubic-bezier(.2,.8,.2,1);z-index:2}.assistant-launcher:before,.assistant-launcher:after{content:\"\";position:absolute;top:50%;left:50%;width:22px;height:2px;border-radius:999px;background:#0f6cae;opacity:0;transform:translate(-50%,-50%) scale(.6) rotate(0);transition:opacity .18s ease,transform .22s ease;z-index:1}.assistant-launcher:before{transform:translate(-50%,-50%) scale(.6) rotate(45deg)}.assistant-launcher:after{transform:translate(-50%,-50%) scale(.6) rotate(-45deg)}.assistant-launcher:hover,.assistant-launcher:focus-visible{border-color:#ec489975!important;background:radial-gradient(circle at 30% 18%,#fff,transparent 38%),linear-gradient(145deg,#ffedd5,#ede9fe,#fce7f3)!important;box-shadow:0 0 0 3px #a855f71a,0 16px 34px #6d28d938!important;transform:translateY(-2px)}.assistant-launcher.is-open{background:#fff!important;box-shadow:0 0 0 2px #0078c838,0 14px 32px #0f172a2e!important;transform:translateY(0)}.assistant-launcher.is-open:before,.assistant-launcher.is-open:after{opacity:1}.assistant-launcher.is-open:before{transform:translate(-50%,-50%) scale(1) rotate(45deg)}.assistant-launcher.is-open:after{transform:translate(-50%,-50%) scale(1) rotate(-45deg)}.mascot{position:relative;display:inline-grid;width:54px;height:54px;place-items:center;transform-origin:50% 72%;transition:opacity .18s ease,transform .24s ease,filter .24s ease;z-index:0}.mascot-aura{position:absolute;inset:5px;border-radius:50%;background:conic-gradient(from 25deg,#f472b66b,#fbbf2452,#2dd4bf57,#8b5cf66b,#f472b66b);filter:blur(7px);animation:mascot-aura 3s ease-in-out infinite}.mascot-art{position:relative;width:100%;height:100%;overflow:visible;filter:drop-shadow(0 5px 5px rgba(2,75,116,.2));animation:mascot-idle 3.4s ease-in-out infinite}.mascot-shell{fill:#7c3aed}.mascot-ear-left{fill:#ec4899}.mascot-ear-right{fill:#f97316}.mascot-ear{transform-box:fill-box;transform-origin:center}.mascot-face{fill:#211747;stroke:#ffffff4d;stroke-width:1}.mascot-signal{fill:#facc15;stroke:#fff;stroke-width:1.5;transform-box:fill-box;transform-origin:center;animation:mascot-signal 2.2s ease-out infinite}.mascot-antenna,.mascot-sparkle,.mascot-shell-shine,.mascot-smile,.mascot-mark{fill:none;stroke-linecap:round;stroke-linejoin:round}.mascot-antenna{stroke:#6d28d9;stroke-width:2.5}.mascot-sparkle{stroke:#ec4899;stroke-width:2;transform-box:fill-box;transform-origin:center;animation:mascot-sparkle 3.4s ease-in-out infinite}.mascot-shell-shine{stroke:#e9d5ffd1;stroke-width:2}.mascot-eye{fill:#5eead4;transform-box:fill-box;transform-origin:center;animation:mascot-blink 5.2s ease-in-out infinite}.mascot-smile{stroke:#fbbf24;stroke-width:2}.mascot-mark{stroke:#ffffffd1;stroke-width:2.2}.assistant-launcher:hover .mascot-art,.assistant-launcher:focus-visible .mascot-art{animation:mascot-greet .7s cubic-bezier(.2,.8,.2,1)}.assistant-launcher:hover .mascot-ear-right,.assistant-launcher:focus-visible .mascot-ear-right{animation:mascot-ear-wave .7s ease-in-out}.assistant-launcher.is-open .mascot{filter:saturate(1.08);opacity:.24;transform:scale(.82) rotate(-5deg)}.mascot.large{width:52px;height:52px;flex:0 0 auto}@keyframes mascot-idle{0%,to{transform:translateY(0) rotate(0)}50%{transform:translateY(-2px) rotate(1deg)}}@keyframes mascot-greet{0%,to{transform:translateY(0) rotate(0)}35%{transform:translateY(-4px) rotate(-5deg)}65%{transform:translateY(-2px) rotate(4deg)}}@keyframes mascot-ear-wave{0%,to{transform:rotate(0) scaleY(1)}50%{transform:rotate(-12deg) scaleY(1.12)}}@keyframes mascot-blink{0%,45%,49%,to{transform:scaleY(1)}47%{transform:scaleY(.12)}}@keyframes mascot-signal{0%,55%,to{opacity:1;transform:scale(1)}70%{opacity:.55;transform:scale(1.42)}}@keyframes mascot-sparkle{0%,62%,to{opacity:0;transform:scale(.5) rotate(0)}72%{opacity:1;transform:scale(1) rotate(90deg)}84%{opacity:0;transform:scale(.7) rotate(150deg)}}@keyframes mascot-aura{0%,to{opacity:.45;transform:scale(.88)}50%{opacity:.85;transform:scale(1.08)}}.assistant-window{position:relative;width:100%;height:100%;min-height:0;border:1px solid rgba(148,163,184,.24);border-radius:24px;background:#fffffff5;box-shadow:0 24px 70px #0f172a33,0 0 0 1px #ffffffad inset;overflow:hidden;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.assistant-panel{display:grid;grid-template-rows:auto 1fr auto;height:100%;min-height:0;border-radius:inherit;background:linear-gradient(180deg,#f8fafcd1,#f1f5f9f5),var(--max-canvas, #f8fafc);overflow:hidden}.assistant-header,.assistant-composer{display:flex;gap:12px;align-items:center;padding:16px 18px;background:#ffffffeb;border-bottom:1px solid rgba(226,232,240,.86)}.assistant-identity{display:grid;gap:5px;min-width:0}.assistant-name{margin:0;width:fit-content;color:var(--max-accent, #2563eb);font:inherit;font-weight:600}.assistant-subtitle{color:#64748b;font-size:10px;font-weight:600;letter-spacing:.1em;line-height:1.2;text-transform:uppercase}.sources span{color:#64748b;font-size:12px;font-weight:600}.assistant-header .header-action:first-of-type{margin-left:auto}.assistant-header .header-action{width:38px;height:38px;margin-left:0;color:#475569;background:transparent}.assistant-header .header-action:hover{background:#0f172a0f}.assistant-messages{min-height:0;overflow:auto;padding:18px;scrollbar-width:thin}.assistant-messages,.assistant-table-wrap,.assistant-rota-scroll{scrollbar-color:#cbd5e1 transparent;scrollbar-width:thin}.assistant-messages::-webkit-scrollbar,.assistant-table-wrap::-webkit-scrollbar,.assistant-rota-scroll::-webkit-scrollbar{width:6px;height:6px}.assistant-messages::-webkit-scrollbar-track,.assistant-table-wrap::-webkit-scrollbar-track,.assistant-rota-scroll::-webkit-scrollbar-track{background:transparent}.assistant-messages::-webkit-scrollbar-thumb,.assistant-table-wrap::-webkit-scrollbar-thumb,.assistant-rota-scroll::-webkit-scrollbar-thumb{border-radius:999px;background:#cbd5e1}.message{position:relative;width:fit-content;max-width:92%;margin-bottom:14px;padding:12px;border:1px solid var(--border-color, #e2e8f0);border-radius:16px;background:#fff;box-shadow:0 1px 2px #0f172a14,0 10px 24px #0f172a0f;-webkit-user-select:text;user-select:text}.message.assistant{width:100%;max-width:100%}.message.user{width:fit-content;max-width:88%;margin-left:auto;color:#fff;background:var(--primary-color, #2563eb);border-color:var(--border-color, #e2e8f0);border-bottom-right-radius:6px}.message.user p{color:inherit}.message.error{border-color:var(--danger-color, #dc2626)}.message.streaming{padding:0;border:0;color:var(--text-color-secondary, #64748b);background:transparent;box-shadow:none;font-style:italic}.streaming-progress{background:linear-gradient(100deg,var(--max-muted, #64748b) 20%,var(--primary-color, #2563eb) 42%,#a855f7 50%,var(--primary-color, #2563eb) 58%,var(--max-muted, #64748b) 80%);background-size:220% 100%;background-clip:text;-webkit-background-clip:text;-webkit-text-fill-color:transparent;white-space:pre-line;animation:assistant-progress-shimmer 2.2s ease-in-out infinite}@keyframes assistant-progress-shimmer{0%{background-position:120% 0}to{background-position:-20% 0}}.message p{margin:0;line-height:1.45}.assistant-result{color:#1e293b}.assistant-cards{display:grid;gap:10px;margin-top:12px}.assistant-card{overflow:hidden;border:1px solid #e2e8f0;border-radius:12px;background:#fff;box-shadow:0 3px 12px #0f172a0d;font-weight:400}.assistant-card>header{display:grid;gap:3px;padding:13px 16px;border-bottom:1px solid #e2e8f0}.assistant-card-title{color:#0f172a;font-size:14px;font-weight:600}.assistant-card-subtitle,.assistant-card>footer{color:#64748b;font-size:12px}.assistant-card-metrics{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));padding:16px}.assistant-card-metric{display:grid;min-width:0;align-content:start;gap:5px}.assistant-card-metric-wide{grid-column:1/-1}.assistant-card-label{color:#64748b;font-size:11px;font-weight:500;letter-spacing:.01em;line-height:1.25}.assistant-card-value{color:#0f172a;font-size:14px;font-weight:600;line-height:1.4;overflow-wrap:anywhere}.assistant-card-metric[data-tone=positive] .assistant-card-value{color:#047857}.assistant-card-metric[data-tone=warning] .assistant-card-value{color:#b45309}.assistant-card :is(strong,b){font-weight:600}.assistant-card>footer{padding:0 16px 14px}:host ::ng-deep .assistant-markdown{line-height:1.45}:host ::ng-deep .assistant-markdown>:first-child{margin-top:0}:host ::ng-deep .assistant-markdown>:last-child{margin-bottom:0}:host ::ng-deep .assistant-markdown p{margin:0 0 8px}:host ::ng-deep .assistant-markdown ul,:host ::ng-deep .assistant-markdown ol{margin:8px 0;padding-left:22px}:host ::ng-deep .assistant-markdown li+li{margin-top:4px}:host ::ng-deep .assistant-markdown strong{font-weight:700}:host ::ng-deep .assistant-markdown code{padding:1px 4px;border-radius:4px;background:#e2e8f0;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:.9em}:host ::ng-deep .assistant-markdown a{color:var(--primary-color, #2563eb);text-decoration:underline}.assistant-status{display:inline-flex;margin-top:8px;padding:3px 8px;border-radius:999px;color:#475569;background:#e2e8f0;font-size:11px;font-weight:600;text-transform:capitalize}.pending-action{display:grid;gap:9px;margin-top:12px;padding:12px;border:1px solid #f59e0b;border-radius:12px;background:#fffbeb}.pending-action-heading{display:flex;align-items:center;justify-content:space-between;color:#92400e}.pending-action-heading span{padding:2px 7px;border-radius:999px;color:#78350f;background:#fde68a;font-size:11px;font-weight:700}.pending-action small{color:#78716c}.pending-action-buttons{display:flex;gap:8px}.action-decision{color:#475569;font-weight:600}.assistant-sources{display:grid;gap:4px;margin-top:12px;padding-top:10px;border-top:1px solid #e2e8f0;color:#64748b;font-size:12px}.assistant-shift-groups,.assistant-shift-group{display:grid;gap:10px}.assistant-shift-groups,.assistant-rota{margin-top:12px}.assistant-shift-group h3,.assistant-rota h3{margin:0;color:#0f172a;font-size:13px;font-weight:600}.assistant-shift-card-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:9px}.assistant-rota{display:grid;gap:10px}.assistant-rota-heading{display:grid;gap:8px}.assistant-rota-summary{display:flex;flex-wrap:wrap;gap:7px}.assistant-rota-summary>span{display:grid;gap:2px;min-width:86px;padding:7px 9px;border:1px solid #e2e8f0;border-radius:8px;background:#f8fafc}.assistant-rota-summary small{color:#64748b;font-size:9px;font-weight:600;text-transform:uppercase}.assistant-rota-summary strong{color:#334155;font-size:11px}.assistant-rota-scroll{max-width:100%;overflow-x:auto;border:1px solid #e2e8f0;border-radius:10px;background:#fff}.assistant-rota-week{min-width:1288px}.assistant-rota-week+.assistant-rota-week{border-top:1px solid #cbd5e1}.assistant-rota-week-heading{display:flex;align-items:center;justify-content:space-between;padding:8px 10px;color:#334155;background:#f1f5f9}.assistant-rota-week-heading strong{font-size:12px}.assistant-rota-week-heading span{color:#64748b;font-size:10px}.assistant-rota-week-grid{display:grid;grid-template-columns:repeat(7,minmax(184px,1fr))}.assistant-rota-day{min-width:0;min-height:120px;border-right:1px solid #e2e8f0}.assistant-rota-day:last-child{border-right:0}.assistant-rota-day>header{display:flex;align-items:baseline;justify-content:space-between;padding:7px 8px;border-bottom:1px solid #e2e8f0;color:#334155;background:#f8fafc}.assistant-rota-day>header strong{font-size:10px}.assistant-rota-day>header span{color:#64748b;font-size:9px}.assistant-rota-day-shifts{display:grid;gap:7px;padding:7px}.assistant-rota-empty,.assistant-rota-no-weeks{margin:0;color:#94a3b8;font-size:10px;font-style:italic}.assistant-visualisations{display:grid;gap:10px;margin-top:12px}.assistant-visualisation{display:grid;gap:12px;padding:13px;border:1px solid #dbeafe;border-radius:14px;background:linear-gradient(145deg,#f8fbff,#fff)}.assistant-visualisation h3{margin:0;color:#0f172a;font-size:13px;font-weight:600}.assistant-export-heading{display:flex;min-width:0;gap:8px;align-items:center}.assistant-export-heading h3{min-width:0}.assistant-export-action{flex:0 0 auto;margin-left:auto;padding:0;color:inherit;background:transparent;border-color:transparent;box-shadow:none}:host ::ng-deep .assistant-export-action .p-button-icon{font-size:20px!important}.assistant-export-action-pdf{color:#d32f2f}.assistant-export-action-excel{color:#217346}.assistant-export-action-pdf:hover{color:#b71c1c;background:transparent;border-color:transparent}.assistant-export-action-excel:hover{color:#185c37;background:transparent;border-color:transparent}.assistant-doughnut-layout{display:grid;grid-template-columns:112px minmax(0,1fr);gap:14px;align-items:center}.assistant-doughnut{position:relative;display:grid;place-items:center;width:112px;aspect-ratio:1}.assistant-doughnut svg{width:100%;height:100%;transform:rotate(-90deg)}.assistant-doughnut circle{fill:none;stroke-width:6}.assistant-doughnut-track{stroke:#e2e8f0}.assistant-doughnut-segment{transition:stroke-dasharray .18s ease}.assistant-doughnut>span{position:absolute;display:grid;color:#64748b;font-size:9px;line-height:1.1;text-align:center}.assistant-doughnut>span strong{color:#0f172a;font-size:18px}.assistant-chart-legend{display:grid;gap:7px;min-width:0}.assistant-chart-legend-item{display:grid;grid-template-columns:9px minmax(0,1fr) auto;gap:7px;align-items:center;color:#475569;font-size:11px}.assistant-chart-legend-item i{width:9px;height:9px;border-radius:999px}.assistant-chart-legend-item strong,.assistant-bar-label strong{color:#0f172a;font-size:11px;font-weight:600}.assistant-bar-chart,.assistant-bar-row{display:grid;gap:6px}.assistant-bar-chart{gap:11px}.assistant-bar-label{display:flex;gap:12px;align-items:baseline;justify-content:space-between;color:#475569;font-size:11px}.assistant-bar-track{height:9px;overflow:hidden;border-radius:999px;background:#e2e8f0}.assistant-bar-track i{display:block;height:100%;min-width:0;border-radius:var(--max-frame-radius, 0);transition:width .18s ease}.assistant-tables{display:grid;gap:10px;margin-top:12px}.assistant-table-section{display:grid;gap:6px}.assistant-table-section h3{margin:0;color:#0f172a;font-size:13px;font-weight:600}.assistant-table-wrap{overflow:auto;max-height:450px;border:1px solid var(--border-color, #e2e8f0);border-radius:var(--border-radius, 6px)}.assistant-table-wrap table{width:100%;min-width:420px;border-collapse:collapse;background:#fff}.assistant-table-wrap th,.assistant-table-wrap td{padding:8px 10px;border-bottom:1px solid var(--border-color, #e2e8f0);color:#334155;font-size:12px;line-height:1.35;text-align:left;vertical-align:top}.assistant-table-wrap th{position:sticky;z-index:1;top:0;color:#475569;font-weight:600;background:#f8fafc}.assistant-table-wrap tr:last-child td{border-bottom:0}.assistant-table-actions{display:flex;flex-wrap:wrap;gap:6px;min-width:150px}.assistant-table-pagination{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px;color:#64748b;font-size:12px}.assistant-table-page-error{margin:0;color:#b91c1c;font-size:12px}.details-toggle{display:flex;width:fit-content;margin:10px 0 0 auto;padding:0;border:0;color:var(--primary-color, #2563eb);background:transparent;font:inherit;font-size:13px;font-weight:400;text-decoration:underline;text-underline-offset:3px;cursor:pointer}.details-toggle:hover{color:var(--primary-dark-color, #1d4ed8)}.details-toggle:focus-visible{outline:2px solid var(--primary-color, #2563eb);outline-offset:3px}.developer-details{display:grid;gap:12px;margin-top:12px;padding:12px;border:1px solid var(--border-color, #e2e8f0);border-radius:10px;background:#f8fafc}.developer-details-header h3,.developer-details-header p{margin:0}.developer-details-header h3{color:#0f172a;font-size:13px;font-weight:600}.developer-details-header p{margin-top:2px;color:#64748b;font-size:11px}.workflow-trace{display:grid;gap:0;margin:0;padding:0;list-style:none}.workflow-step{display:block;min-width:0}.workflow-category{color:#64748b;font-size:9px;font-weight:600;letter-spacing:.06em;text-transform:uppercase}.workflow-meta{display:grid;flex:0 0 auto;gap:2px;justify-items:end;color:#64748b;font-size:9px}.workflow-status{padding:2px 5px;border-radius:999px;color:#334155;background:#e2e8f0;font-weight:600;text-transform:capitalize}.workflow-step[data-status=succeeded] .workflow-status{color:#166534;background:#dcfce7}.workflow-step[data-status=failed] .workflow-status{color:#991b1b;background:#fee2e2}.trace-json{display:grid;gap:4px;margin-top:8px}.trace-json>span{color:#64748b;font-size:10px;font-weight:600;text-transform:uppercase}.trace-json pre{max-height:280px;margin:0;padding:8px;overflow:auto;border-radius:6px;color:#dbeafe;background:#0f172a;font-size:10px;line-height:1.45;white-space:pre-wrap;overflow-wrap:anywhere}.trace-error{display:grid;gap:3px;margin-top:8px;padding:8px;border-left:3px solid #dc2626;border-radius:4px;color:#991b1b;background:#fef2f2;font-size:11px}.developer-details-header{display:flex;gap:12px;align-items:flex-start;justify-content:space-between}.developer-eyebrow{color:var(--text-color, #0f172a);font-size:9px;font-weight:600;letter-spacing:.08em;text-transform:uppercase}.trace-section-label{color:var(--text-color, #0f172a);font-size:9px;font-weight:600;text-decoration:underline;text-underline-offset:3px}.trace-run-summary{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:7px}.trace-metric{display:grid;gap:3px;min-width:0;padding:9px;border:1px solid #e2e8f0;border-radius:8px;background:#fff}.trace-metric span,.trace-loop-policy span{color:#64748b;font-size:9px;font-weight:600}.trace-metric strong{color:#0f172a;font-size:13px}.trace-loop-policy{display:grid;grid-template-columns:minmax(0,1fr) auto;grid-column:1/-1;gap:5px 12px;align-items:center;padding:10px;border:1px solid #c7d2fe;border-radius:9px;background:#eef2ff}.trace-loop-policy div{display:grid;gap:2px}.trace-loop-policy strong{color:#312e81;font-size:11px}.trace-loop-policy p{grid-column:1/-1;margin:0;color:#475569;font-size:10px;line-height:1.45}.trace-no-loop{padding:3px 7px;border-radius:999px;color:#166534!important;background:#dcfce7;font-weight:600!important}.workflow-summary{margin:9px 0 0;color:#475569;font-size:10.5px;line-height:1.5}.trace-technology{display:grid;gap:6px;margin-top:10px;padding:8px;border:1px solid #dbeafe;border-radius:7px;background:#f8fbff}.trace-inline-facts{display:flex;flex-wrap:wrap;gap:5px}.trace-inline-facts>span{display:grid;gap:1px;max-width:100%;padding:4px 6px;border-radius:5px;color:#1e293b;background:#fff;font-size:9.5px;overflow-wrap:anywhere}.trace-inline-facts small{color:#64748b;font-size:8px;font-weight:600;text-transform:uppercase}.trace-control{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:4px 8px;margin-top:8px;padding:8px;border-left:3px solid #8b5cf6;border-radius:5px;background:#f5f3ff}.trace-control>div{display:grid;gap:2px}.trace-control strong,.trace-control>span{color:#5b21b6;font-size:9.5px}.trace-control p{grid-column:1/-1;margin:0;color:#475569;font-size:9.5px;line-height:1.4}.trace-query,.trace-section,.trace-arguments,.trace-ranking-wrap{display:grid;gap:5px;margin-top:10px}.trace-query>span,.trace-transform>div>span,.trace-vector>span,.trace-payload-grid section>span,.trace-tool-call>span,.trace-supabase-call span,.trace-decision>span{color:#64748b;font-size:9px;font-weight:600;text-transform:uppercase}.trace-query>span,.trace-vector>span,.trace-payload-grid section>span,.trace-tool-call>span,.trace-decision>span{color:var(--text-color, #0f172a);text-decoration:underline;text-underline-offset:3px}.trace-query blockquote{margin:0;padding:8px 10px;border-left:3px solid #2563eb;border-radius:5px;color:#172554;background:#eff6ff;font-size:11px;font-weight:600;line-height:1.45}.trace-query-compact blockquote{border-color:#8b5cf6;color:#4c1d95;background:#f5f3ff}.trace-card-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:7px;margin-top:9px}.trace-data-card{min-width:0;padding:8px;border:1px solid #e2e8f0;border-radius:7px;background:#f8fafc}.trace-data-card-accent{border-color:#bfdbfe;background:#eff6ff}.trace-data-card h5{margin:0 0 5px;color:var(--text-color, #0f172a);font-size:10px;font-weight:600;text-decoration:underline;text-underline-offset:3px}.trace-field-list,.trace-argument-grid{display:grid;gap:4px;margin:0}.trace-field-list>div{display:grid;grid-template-columns:minmax(70px,.7fr) minmax(0,1.3fr);gap:6px}.trace-field-list dt,.trace-argument-grid dt{color:#64748b;font-size:8.5px}.trace-field-list dd,.trace-argument-grid dd{margin:0;color:#1e293b;font-size:9px;font-weight:600;overflow-wrap:anywhere}.trace-transform{display:grid;grid-template-columns:minmax(0,1fr) 18px minmax(0,1fr);gap:6px;align-items:stretch;margin-top:10px}.trace-transform>div{display:grid;gap:5px;padding:9px;border:1px solid #e2e8f0;border-radius:7px;background:#f8fafc}.trace-transform .trace-transform-result{border-color:#bfdbfe;background:#eff6ff}.trace-transform p{margin:0;color:#1e293b;font-size:10px;font-weight:600;line-height:1.4}.trace-transform-arrow{display:grid;place-items:center;color:#2563eb;font-size:16px;font-weight:600}.trace-entity-list{display:flex;flex-wrap:wrap;gap:5px}.trace-entity-list>span{display:flex;gap:5px;align-items:center;padding:4px 7px;border:1px solid #fed7aa;border-radius:999px;color:#9a3412;background:#fff7ed;font-size:9.5px}.trace-entity-list small{color:#c2410c;font-size:7.5px;font-weight:600;text-transform:uppercase}.trace-stat-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px;margin-top:8px}.trace-stat-grid>div{display:grid;gap:2px;padding:7px;border:1px solid #e2e8f0;border-radius:6px}.trace-stat-grid span{color:#64748b;font-size:8.5px}.trace-stat-grid strong{color:#0f172a;font-size:10px;overflow-wrap:anywhere}.trace-vector{display:grid;gap:4px;margin-top:7px}.trace-vector code{padding:7px;overflow:auto;border-radius:5px;color:#c4b5fd;background:#1e1b4b;font-size:8.5px;white-space:nowrap}.trace-supabase-call{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px;margin-top:10px;padding:9px;border:1px solid #a7f3d0;border-radius:7px;background:#ecfdf5}.trace-supabase-call>div{display:grid;gap:2px}.trace-supabase-call strong{color:#065f46;font-size:10px;overflow-wrap:anywhere}.trace-table-list{grid-column:1/-1}.trace-table-list>div{display:flex;flex-wrap:wrap;gap:4px}.trace-table-list code{padding:3px 5px;border-radius:4px;color:#065f46;background:#d1fae5;font-size:8.5px}.trace-decision{display:grid;gap:4px;margin-top:7px;padding:9px;border-left:3px solid #16a34a;border-radius:5px;background:#f0fdf4}.trace-decision strong{color:#14532d;font-size:11px}.trace-decision div{display:flex;flex-wrap:wrap;gap:8px;color:#166534;font-size:8.5px}.trace-ranking-wrap{overflow:auto}.trace-ranking{width:100%;min-width:610px;border-collapse:collapse;font-size:8.5px}.trace-ranking th,.trace-ranking td{padding:6px;border-bottom:1px solid #e2e8f0;color:#475569;text-align:right;vertical-align:top}.trace-ranking th{color:#64748b;background:#f8fafc;font-size:8px;text-transform:uppercase}.trace-ranking th:nth-child(2),.trace-ranking td:nth-child(2){text-align:left}.trace-ranking td:nth-child(2){display:grid;gap:2px;min-width:145px}.trace-ranking strong{color:#1e293b;font-size:9px}.trace-ranking code{color:#64748b;font-size:7.5px}.trace-argument-grid{grid-template-columns:repeat(2,minmax(0,1fr));margin-top:3px}.trace-argument-grid>div{min-width:0;padding:7px;border:1px solid #e2e8f0;border-radius:6px;background:#f8fafc}.trace-tool-call,.trace-api-route{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin-top:8px;padding:8px;border-radius:6px;color:#dbeafe;background:#0f172a}.trace-tool-call>span{width:100%;color:#94a3b8}.trace-tool-call strong{color:#bfdbfe;font-size:10px}.trace-tool-call pre,.trace-payload-grid pre{width:100%;max-height:220px;margin:0;overflow:auto;color:#dbeafe;font-size:9px;line-height:1.45;white-space:pre-wrap;overflow-wrap:anywhere}.trace-api-route>code{flex:1 1 180px;color:#e2e8f0;font-size:9px;overflow-wrap:anywhere}.trace-http-method,.trace-http-status{padding:3px 6px;border-radius:4px;color:#fff;background:#2563eb;font-size:8.5px;font-weight:600}.trace-http-status.success{color:#bbf7d0;background:#166534}.trace-http-status.error{color:#fecaca;background:#991b1b}.trace-payload-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px;margin-top:7px}.trace-payload-grid section{display:grid;gap:5px;min-width:0;padding:8px;border:1px solid #334155;border-radius:6px;background:#0f172a}.trace-payload-grid section>span{color:#94a3b8}.trace-error.trace-warning{border-left-color:#f59e0b;color:#92400e;background:#fffbeb}.trace-error-legacy{display:none}.trace-error-heading{font-size:10px}.details-dialog-backdrop{position:fixed;inset:0;z-index:20;display:grid;padding:14px;place-items:center;background:#0f172a7a;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}.details-dialog-backdrop .developer-details{display:block;width:100%;max-height:100%;margin:0;padding:0 14px 14px;overflow:auto;overscroll-behavior:contain;border:0;border-radius:14px;background:#fff;box-shadow:0 24px 70px #0f172a4d}.details-dialog-backdrop .developer-details-header{position:sticky;top:0;z-index:3;margin:0 -14px 14px;padding:14px;border-bottom:1px solid #e2e8f0;background:#fffffff7;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}.details-dialog-actions{display:flex;flex:0 0 auto;gap:7px;align-items:center}.details-dialog-close{display:grid;width:30px;height:30px;padding:0;place-items:center;border:1px solid #e2e8f0;border-radius:8px;color:#475569;background:#fff;cursor:pointer}.details-dialog-close:hover{color:#0f172a;background:#f1f5f9}.details-dialog-close:focus-visible{outline:2px solid #2563eb;outline-offset:2px}.details-dialog-backdrop .trace-run-summary{margin-bottom:6px;padding-bottom:14px;border-bottom:1px solid #cbd5e1}.details-dialog-backdrop .trace-metric{padding:0 9px;border:0;border-right:1px solid #e2e8f0;border-radius:0;background:transparent}.details-dialog-backdrop .trace-metric:nth-child(4){border-right:0}.details-dialog-backdrop .trace-loop-policy{margin-top:5px;padding:9px 0 0;border:0;border-top:1px solid #e2e8f0;border-radius:0;background:transparent}.details-dialog-backdrop .workflow-trace{display:block}.details-dialog-backdrop .workflow-step{display:block;border-bottom:1px solid #cbd5e1}.workflow-section{display:block}.workflow-step-toggle{display:flex;gap:14px;align-items:center;justify-content:space-between;width:100%;padding:14px 2px;border:0;color:inherit;background:transparent;font:inherit;text-align:left;cursor:pointer}.workflow-step-toggle:hover{background:#f8fafc}.workflow-step-toggle:focus-visible{outline:2px solid #2563eb;outline-offset:-2px}.workflow-step-toggle>div:first-child{display:grid;min-width:0;gap:2px}.workflow-step-toggle h4{margin:0;color:var(--text-color, #0f172a);font-size:12px;font-weight:600;line-height:1.4;text-decoration:underline;text-decoration-color:#94a3b8;text-underline-offset:4px}.workflow-step-number{display:block;color:var(--primary-color, #2563eb);font-size:13px;font-weight:600}.workflow-expand-icon{color:#64748b;font-size:10px}.workflow-step-content{padding:0 2px 16px}.details-dialog-backdrop .workflow-summary{margin-top:0;padding-bottom:10px;border-bottom:1px solid #e2e8f0}.details-dialog-backdrop .trace-technology,.details-dialog-backdrop .trace-control{padding:9px 0;border:0;border-bottom:1px solid #e2e8f0;border-radius:0;background:transparent}.details-dialog-backdrop .trace-control{border-left:0}.details-dialog-backdrop .trace-inline-facts>span{padding:0 8px 0 0;border-right:1px solid #e2e8f0;border-radius:0;background:transparent}.details-dialog-backdrop :is(h3,h4,h5,strong,.workflow-status,.trace-section-label,.developer-eyebrow){font-weight:600!important}@media (max-width: 520px){.trace-run-summary,.trace-card-grid,.trace-stat-grid,.trace-payload-grid,.trace-argument-grid,.trace-transform{grid-template-columns:1fr}.trace-transform-arrow{transform:rotate(90deg)}}.suggestions{display:grid;gap:0;margin-top:12px}.entity-options{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin-top:12px}.suggestion-chip{justify-content:flex-start;width:100%;padding:6px 0;border:1px solid transparent;border-radius:999px;color:var(--primary-color, #2563eb);background:transparent;font-weight:600;box-shadow:none;text-align:left;transition:padding .16s ease,border-color .16s ease,background .16s ease,box-shadow .16s ease}.suggestion-chip:hover{padding:6px 12px;border-color:rgba(var(--primary-color-rgb, 37, 99, 235),.28);color:var(--primary-color, #2563eb);background:rgba(var(--primary-color-rgb, 37, 99, 235),.08);box-shadow:0 4px 14px #0f172a0f}.response-details{display:grid;gap:12px;margin-top:12px}.response-section{display:grid;gap:8px;padding-bottom:12px;border-bottom:1px solid var(--border-color, #e2e8f0)}.response-section:last-child{padding-bottom:0;border-bottom:0}.response-section h3{margin:0;color:#0f172a;font-size:13px;font-weight:600}.quoted{padding:8px 10px;border-left:5px solid var(--primary-color, #2563eb);border-radius:var(--border-radius, 6px);color:#1e293b;background:#f8fafc}.detail-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;margin:0}.detail-grid div{min-width:0;padding:8px;border-radius:var(--border-radius, 6px);background:#f8fafc}.detail-grid dt{margin-bottom:3px;color:#64748b;font-size:11px;font-weight:600;text-transform:uppercase}.detail-grid dd{margin:0;color:#334155;font-size:13px;font-weight:600;line-height:1.35;overflow-wrap:anywhere}.detail-grid dd span{display:block;margin-top:2px;color:#64748b;font-size:11px}.api-call-summary,.json-block{display:grid;gap:6px;padding:8px;border-radius:var(--border-radius, 6px);background:#f8fafc}.api-call-summary .detail-label,.json-block .detail-label{color:#64748b;font-size:11px;font-weight:600;text-transform:uppercase}.api-call-summary code{color:var(--secondary-color, #0f172a);font-weight:600;white-space:normal;word-break:break-word}.json-block pre{max-height:220px;margin:0;overflow:auto;color:#0f172a;font-size:12px;line-height:1.45;white-space:pre-wrap;overflow-wrap:anywhere}.assistant-composer{padding:14px 16px 16px;border-top:1px solid rgba(226,232,240,.9);border-bottom:0;box-shadow:0 -10px 30px #0f172a0a}.assistant-composer textarea{flex:1;min-height:46px;max-height:120px;border-radius:18px;background:#fff;resize:vertical}.assistant-composer button[type=submit]{width:44px;height:44px;border-radius:16px}@keyframes pulse{to{opacity:.35;transform:translateY(-2px)}}@media (prefers-reduced-motion: reduce){.mascot-aura,.mascot-art,.mascot-eye,.mascot-signal,.mascot-sparkle,.assistant-launcher:hover .mascot-art,.assistant-launcher:focus-visible .mascot-art,.assistant-launcher:hover .mascot-ear-right,.assistant-launcher:focus-visible .mascot-ear-right{animation:none}.assistant-launcher,.mascot{transition-duration:.01ms}}@media (max-width: 640px){.assistant-messages{padding:14px}.detail-grid,.entity-options,.assistant-card-metrics{grid-template-columns:1fr}.assistant-card-metric{padding:0}}\n", ":host{--max-accent: var(--max-assistant-accent, #1a73e8);--max-accent-strong: var(--max-assistant-accent-strong, #1557b0);--max-canvas: var(--max-assistant-canvas, #f8f9fa);--max-surface: var(--max-assistant-surface, #ffffff);--max-surface-soft: color-mix(in srgb, var(--max-accent) 6%, var(--max-surface));--max-text: var(--max-assistant-text, #1f1f1f);--max-muted: var(--max-assistant-muted, #5f6368);--max-border: var(--max-assistant-border, #dfe1e5);--max-success: var(--max-assistant-success, #188038);--max-warning: var(--max-assistant-warning, #b06000);--max-danger: var(--max-assistant-danger, #b3261e);--max-support-text: var(--max-assistant-support-text, #3c4043);--max-control-radius: var(--max-assistant-control-radius, 6px);--max-frame-radius: var(--max-assistant-frame-radius, 0px);--max-sparkles-gradient: linear-gradient( 135deg, color-mix(in srgb, var(--max-accent) 58%, white) 0%, var(--max-accent) 46%, color-mix(in srgb, var(--max-accent) 55%, var(--max-accent-strong)) 72%, var(--max-accent-strong) 100% );--max-header-action-size: 40px;--max-header-content-size: 20px;--primary-color: var(--max-accent);--primary-color-rgb: var(--max-assistant-accent-rgb, 26, 115, 232);--primary-dark-color: var(--max-accent-strong);--background: var(--max-canvas);--background-color: var(--max-canvas);--panel-background: var(--max-surface);--text-color: var(--max-text);--text-color-secondary: var(--max-muted);--border-color: var(--max-border);--success-color: var(--max-success);--warning-color: var(--max-warning);--error-color: var(--max-danger);--danger-color: var(--max-danger);--border-radius: var(--max-control-radius);position:relative;display:block;width:100%;height:100%;min-height:0;isolation:isolate;color:var(--max-text);font-family:Arial,Helvetica,sans-serif;font-size:16px;font-weight:400;line-height:normal;text-align:left;color-scheme:light}:host,:host *{box-sizing:border-box}:host button,:host ::ng-deep .p-button-label{text-transform:capitalize}.max-assistant-sparkles{display:inline-flex;flex:0 0 auto;align-items:center;justify-content:center;font-size:var(--max-header-content-size);line-height:1;vertical-align:middle;color:transparent;background:var(--assistant-sparkles-gradient, var(--max-sparkles-gradient));background-clip:text;-webkit-background-clip:text;-webkit-text-fill-color:transparent;filter:drop-shadow(0 2px 3px rgba(60,64,67,.18))}.assistant-window{position:relative;inset:auto;width:100%;height:100%;max-height:none;overflow:hidden;opacity:1;visibility:visible;pointer-events:auto;translate:none;transform:none;border:0;border-radius:var(--max-frame-radius);background:var(--max-canvas);box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none;transition:none}.assistant-panel{grid-template-rows:72px minmax(0,1fr) auto;color:var(--max-text);background:radial-gradient(circle at 48% 0%,color-mix(in srgb,var(--max-accent) 10%,transparent),transparent 46%),radial-gradient(circle at 92% 72%,color-mix(in srgb,#c58af9 8%,transparent),transparent 38%),linear-gradient(145deg,var(--max-canvas),color-mix(in srgb,var(--max-canvas) 94%,#edf3ff))}.assistant-header{display:flex;gap:20px;align-items:center;padding:0 24px;border:0;border-bottom:1px solid var(--max-border);background:color-mix(in srgb,var(--max-canvas) 88%,transparent);-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px)}.assistant-header-actions{display:flex;gap:4px;align-items:center;margin-left:auto}.assistant-identity{display:flex;flex-direction:column}.assistant-name{align-self:flex-start;margin:0;color:transparent;background:var(--assistant-sparkles-gradient, var(--max-sparkles-gradient));background-clip:text;-webkit-background-clip:text;-webkit-text-fill-color:transparent;font:inherit;font-size:var(--max-header-content-size);font-weight:600;line-height:1}.assistant-subtitle{color:var(--max-muted);font-size:12px;font-weight:400;letter-spacing:0;line-height:1;text-transform:none}.assistant-name-row{display:flex;align-items:center;gap:8px}.assistant-beta-tag{padding:3px 6px;color:var(--max-text-color, #475569);font-size:11px;font-weight:700;line-height:1;background:var(--max-accent-color, #e2e8f0);border-radius:4px}.assistant-header .header-action{display:inline-flex;width:var(--max-header-action-size);min-width:var(--max-header-action-size);height:var(--max-header-action-size);align-items:center;justify-content:center;margin:0;padding:0;appearance:none;border:0;border-radius:50%;color:var(--max-muted);background:transparent;font:inherit;line-height:1;cursor:pointer}.assistant-header .header-action-icon{font-size:var(--max-header-content-size);font-weight:400;line-height:1}.assistant-header .header-action:hover{color:var(--max-text);background:var(--max-surface-soft)}.assistant-header .header-action:focus-visible{outline:2px solid var(--max-accent);outline-offset:2px}.assistant-messages{width:min(820px,100%);min-height:0;justify-self:center;box-sizing:border-box;padding:44px 28px 32px;overflow-x:hidden;overflow-y:auto;scrollbar-color:color-mix(in srgb,var(--max-muted) 25%,transparent) transparent;scrollbar-width:thin}.assistant-table-wrap,.assistant-rota-scroll{scrollbar-color:color-mix(in srgb,var(--max-muted) 25%,transparent) transparent;scrollbar-width:thin}.assistant-messages::-webkit-scrollbar-thumb,.assistant-table-wrap::-webkit-scrollbar-thumb,.assistant-rota-scroll::-webkit-scrollbar-thumb{background:color-mix(in srgb,var(--max-muted) 25%,transparent)}.message{width:100%;max-width:100%;box-sizing:border-box;margin:0 0 34px;padding:0;border:0;border-radius:0;color:var(--max-text);background:transparent;box-shadow:none}.message.assistant{width:100%;max-width:100%}.message.user{width:fit-content;max-width:min(76%,640px);margin:0 0 32px auto;padding:13px 18px;border:1px solid var(--max-border);border-radius:18px 18px 6px;color:var(--max-text);background:linear-gradient(135deg,color-mix(in srgb,var(--max-accent) 10%,var(--max-surface)),color-mix(in srgb,var(--max-accent) 5%,var(--max-surface)));box-shadow:0 1px 2px color-mix(in srgb,var(--max-text) 7%,transparent),0 6px 18px color-mix(in srgb,var(--max-accent) 8%,transparent)}.message.user p{color:inherit;font-size:15px;line-height:1.55}.message.error{padding-left:16px;border-left:3px solid var(--max-danger)}.message.streaming{display:flex;gap:10px;align-items:center;padding:0;color:var(--max-muted);background:transparent;font-style:normal}.message.streaming:before{width:16px;height:16px;flex:0 0 auto;border-radius:6px;background:var(--assistant-sparkles-gradient, var(--max-sparkles-gradient));content:\"\";animation:max-thinking 1.4s ease-in-out infinite alternate}.streaming-progress{color:var(--max-muted);font-size:14px;white-space:pre-line}.message p,.assistant-result,:host ::ng-deep .assistant-markdown{color:var(--max-text);font-size:15px;line-height:1.65}:host ::ng-deep .assistant-markdown code{color:var(--max-text);background:color-mix(in srgb,var(--max-muted) 10%,transparent)}.message.welcome{min-height:260px;margin:0;padding-top:clamp(28px,8vh,90px);text-align:center}.message.welcome .assistant-markdown{max-width:650px;margin:0 auto}:host ::ng-deep .message.welcome .assistant-markdown p{margin:0;font-size:clamp(28px,3.2vw,42px);font-weight:500;letter-spacing:-.04em;line-height:1.18}:host ::ng-deep .message.welcome-message .assistant-markdown p{color:var(--max-accent)}.welcome-description{max-width:620px;margin:0 auto!important;margin-top:2rem!important;color:var(--max-text);font-size:16px;line-height:1.6;white-space:pre-line}.support-welcome-card{display:flex;width:min(460px,100%);min-height:70px;gap:13px;align-items:center;margin:22px auto 0;padding:13px 16px;appearance:none;border:1px solid color-mix(in srgb,var(--max-accent) 24%,var(--max-border));border-radius:16px;color:var(--max-support-text);background:linear-gradient(135deg,color-mix(in srgb,var(--max-accent) 10%,var(--max-surface)),var(--max-surface) 58%);box-shadow:0 8px 28px #3c40431a;font:inherit;text-align:left;cursor:pointer;transition:border-color .16s ease,box-shadow .16s ease,transform .16s ease}.support-welcome-card:hover{border-color:color-mix(in srgb,var(--max-accent) 48%,var(--max-border));box-shadow:0 12px 32px #3c404324;transform:translateY(-1px)}.support-welcome-card:focus-visible,.support-ticket-shortcut:focus-visible,.support-ticket-close:focus-visible,.response-feedback-action:focus-visible{outline:2px solid var(--max-accent);outline-offset:2px}.support-welcome-icon,.support-ticket-header-icon,.support-ticket-success-icon{display:inline-flex;width:40px;height:40px;flex:0 0 40px;align-items:center;justify-content:center;border-radius:13px;color:var(--max-accent);background:color-mix(in srgb,var(--max-accent) 13%,var(--max-surface));font-size:18px}.support-welcome-copy{display:flex;min-width:0;flex:1;flex-direction:column;gap:5px}.support-welcome-copy strong{color:var(--max-support-text);font-size:15px;font-weight:600;line-height:1.25}.support-welcome-copy small{color:var(--max-muted);font-size:12px;line-height:1.45}.support-welcome-arrow{flex:0 0 auto;color:var(--max-accent);font-size:16px}@media (min-width: 641px) and (max-height: 850px){.message.welcome{min-height:0;padding-top:22px;padding-bottom:22px}:host ::ng-deep .message.welcome .assistant-markdown p{font-size:clamp(24px,3vw,34px)}.welcome-description{margin-top:1rem!important;font-size:14px;line-height:1.45}.support-welcome-card{min-height:58px;margin-top:14px;padding:10px 13px}}.assistant-cards{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin-top:20px}.assistant-card{overflow:hidden;border:1px solid var(--max-border);border-radius:18px;background:var(--max-surface);box-shadow:none}.assistant-card>header{gap:4px;padding:16px;border-bottom:1px solid var(--max-border)}.assistant-card>header strong{color:var(--max-text);font-size:15px;font-weight:600}.assistant-card>header span,.assistant-card>footer,.assistant-card-metric span{color:var(--max-muted)}.assistant-card-metric{padding:14px;border-color:var(--max-border)}.assistant-card-metric strong{color:var(--max-text);font-size:10px}.assistant-card-metric[data-tone=positive] strong{color:var(--max-success)}.assistant-card-metric[data-tone=warning] strong{color:var(--max-warning)}.assistant-card>footer{padding:10px 16px;border-color:var(--max-border);background:var(--max-surface-soft)}.assistant-search-result>header{display:flex;gap:12px;align-items:center}.assistant-search-result-icon{display:inline-flex;width:36px;height:36px;flex:0 0 36px;align-items:center;justify-content:center;border-radius:12px;color:var(--max-accent);background:var(--max-surface-soft);font-size:16px;font-weight:400;line-height:1}.assistant-search-result-copy{display:grid;min-width:0;gap:4px}.assistant-search-result .suggestions{display:grid;grid-template-columns:repeat(auto-fit,minmax(132px,1fr));gap:10px;margin:0;padding:16px}.assistant-search-result .suggestion-chip{width:100%;min-height:44px;align-items:center;justify-content:flex-start;padding:10px 14px;border-color:var(--max-border);background:var(--max-surface-soft);line-height:1.25}.assistant-search-result .suggestion-chip:hover{padding:10px 14px;background:color-mix(in srgb,var(--max-accent) 10%,var(--max-surface))}:host ::ng-deep .assistant-search-result .suggestion-chip .p-button-icon{font-weight:400;line-height:1}.assistant-status{margin-top:12px;padding:0;border-radius:0;color:var(--max-muted);background:transparent;font-size:11px;letter-spacing:.05em;text-transform:uppercase}.pending-action{gap:12px;margin-top:18px;padding:18px;border:1px solid color-mix(in srgb,var(--max-warning) 38%,var(--max-border));border-radius:18px;background:color-mix(in srgb,var(--max-warning) 6%,var(--max-surface))}.pending-action-heading{color:var(--max-text)}.pending-action-heading span{color:var(--max-warning);background:transparent}.pending-action small,.action-decision{color:var(--max-muted)}.assistant-sources{margin-top:20px;padding-top:14px;border-color:var(--max-border);color:var(--max-muted)}.assistant-shift-groups,.assistant-rota{margin-top:20px}.assistant-shift-group h3,.assistant-rota h3,.assistant-rota-summary strong,.assistant-rota-week-heading,.assistant-rota-day>header{color:var(--max-text)}.assistant-rota-summary>span,.assistant-rota-scroll{border-color:var(--max-border);background:var(--max-surface)}.assistant-rota-summary small,.assistant-rota-week-heading span,.assistant-rota-day>header span{color:var(--max-muted)}.assistant-rota-week-heading,.assistant-rota-day>header{background:var(--max-surface-soft)}.assistant-rota-week+.assistant-rota-week,.assistant-rota-day,.assistant-rota-day>header{border-color:var(--max-border)}.assistant-visualisations{grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin-top:20px}.assistant-visualisation{padding:16px;border-color:var(--max-border);border-radius:18px;background:var(--max-surface)}.assistant-visualisation h3,.assistant-doughnut>span strong,.assistant-chart-legend-item strong,.assistant-bar-label strong{color:var(--max-text)}.assistant-chart-legend-item,.assistant-bar-label,.assistant-doughnut>span{color:var(--max-muted)}.assistant-doughnut-track,.assistant-bar-track{stroke:var(--max-border);background:var(--max-border)}.sources span{color:var(--max-muted)}.assistant-tables{gap:18px;margin-top:20px}.assistant-table-section{gap:10px}.assistant-table-section h3{color:var(--max-text);font-size:14px}.assistant-table-wrap{border-color:var(--max-border);border-radius:16px}.assistant-table-wrap table{background:var(--max-surface)}.assistant-table-wrap th,.assistant-table-wrap td{padding:11px 13px;border-color:var(--max-border);color:var(--max-text);font-size:12px}.assistant-table-wrap th{color:var(--max-muted);background:var(--max-surface-soft)}.details-toggle{margin:0 0 0 auto;color:var(--max-accent);font-size:12px;text-decoration:underline;text-underline-offset:3px}.details-toggle:hover{color:var(--max-accent-strong);text-decoration:underline}.suggestions{display:flex;flex-wrap:wrap;gap:8px;margin-top:18px}.capability-options{display:grid;gap:22px;margin-top:18px}.clarification-options{margin-top:18px}.capability-option-section{display:grid;gap:10px}.capability-option-section h3{margin:0;color:var(--max-text);font-size:14px;font-weight:600}.capability-option-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}.capability-option-card{display:grid;grid-template-columns:auto minmax(0,1fr) auto;gap:10px;width:100%;min-height:76px;padding:12px 14px;align-items:center;border:1px solid var(--max-border);border-radius:var(--border-radius, 6px);color:var(--max-text);background:var(--max-surface);box-shadow:none;text-align:left}.capability-option-card:hover:not(:disabled){border-color:color-mix(in srgb,var(--max-accent) 32%,var(--max-border));color:var(--max-text);background:var(--max-surface-soft);box-shadow:none}.capability-option-number{display:inline-flex;min-width:24px;height:24px;align-items:center;justify-content:center;border-radius:50%;color:var(--max-accent-strong);background:var(--max-surface-soft);font-size:12px;font-weight:600}.capability-option-copy{line-height:1.4}.capability-option-arrow{color:var(--max-muted);font-size:13px}.response-actions{display:flex;align-items:center;margin-top:8px}.response-feedback-action{display:inline-flex;width:32px;height:32px;align-items:center;justify-content:center;padding:0;appearance:none;border:0;border-radius:50%;color:var(--max-muted);background:transparent;font:inherit;cursor:pointer}.response-feedback-action:hover{color:var(--max-accent);background:var(--max-surface-soft)}.suggestion-chip{justify-content:flex-start;width:auto;min-height:40px;padding:8px 14px;border:1px solid var(--max-border);border-radius:14px;color:var(--max-text);background:var(--max-surface);font-weight:400;box-shadow:none;text-align:left}.suggestion-chip:hover{padding:8px 14px;border-color:color-mix(in srgb,var(--max-accent) 28%,var(--max-border));color:var(--max-text);background:var(--max-surface-soft);box-shadow:none}.message.welcome .suggestions{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin-top:0}.message.welcome .suggestion-chip{width:100%;min-height:74px;padding:14px 16px;align-items:flex-start;border-radius:18px;line-height:1.35}.message.welcome .suggestion-chip:hover{padding:14px 16px;transform:translateY(-1px)}.assistant-footer{display:flex;width:min(780px,100% - 48px);flex-direction:column;align-items:flex-end;justify-self:center}.support-ticket-shortcut{display:inline-flex;min-height:34px;gap:7px;align-items:center;margin:0 10px 9px 0;padding:7px 12px;appearance:none;border:1px solid color-mix(in srgb,var(--max-accent) 24%,var(--max-border));border-radius:999px;color:var(--max-accent-strong);background:color-mix(in srgb,var(--max-accent) 7%,var(--max-surface));box-shadow:0 2px 8px #3c404314;font:inherit;font-size:13px;font-weight:600;line-height:1;cursor:pointer}.support-ticket-shortcut:hover{border-color:color-mix(in srgb,var(--max-accent) 45%,var(--max-border));background:color-mix(in srgb,var(--max-accent) 11%,var(--max-surface))}.support-ticket-shortcut i{font-size:15px}.assistant-composer{display:flex;width:100%;box-sizing:border-box;gap:8px;align-items:center;margin:0 0 24px;padding:8px 8px 8px 18px;border:1px solid var(--max-border);border-radius:28px;background:var(--max-surface);box-shadow:0 1px 2px #3c404314,0 6px 20px #3c40431a;transition:border-color .16s ease,box-shadow .16s ease}.assistant-composer:focus-within{border-color:color-mix(in srgb,var(--max-accent) 36%,var(--max-border));box-shadow:0 1px 2px #3c404314,0 8px 24px #3c404324}.assistant-composer textarea{flex:1;min-height:44px;height:44px;max-height:132px;box-sizing:border-box;padding:11px 2px;border:0;border-radius:0;outline:0;color:var(--max-text);background:transparent;box-shadow:none;font:inherit;font-size:15px;line-height:22px;resize:none}.assistant-composer textarea::placeholder{color:var(--max-muted);opacity:.84}.assistant-composer textarea:focus{border:0;outline:0;box-shadow:none}.assistant-composer button[type=submit]{width:44px;height:44px;flex:0 0 auto;border-radius:50%;background:var(--max-accent)}.assistant-composer button[type=submit]:disabled{border-color:transparent;color:var(--max-muted);background:transparent;opacity:.5}.support-ticket-overlay{position:absolute;z-index:100;inset:0;display:flex;overflow:auto;align-items:flex-start;justify-content:center;padding:24px;background:#1f1f1f70;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.support-ticket-dialog{position:relative;display:flex;width:min(700px,100%);flex-direction:column;margin:auto 0;border:1px solid var(--max-border);border-radius:22px;color:var(--max-support-text);background:var(--max-surface);box-shadow:0 24px 72px #1f1f1f47}.feedback-dialog{max-height:calc(100% - 48px);overflow:hidden}.feedback-dialog .feedback-form{display:flex;min-height:0;flex:1 1 auto;flex-direction:column;overflow:hidden;padding:0}.feedback-header{position:sticky;z-index:2;top:0;flex:0 0 auto;background:var(--max-surface)}.feedback-header p{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.feedback-form-body{min-height:0;flex:1 1 auto;padding:18px 22px;overflow-y:auto;overscroll-behavior:contain}.feedback-form .support-ticket-fields{gap:12px 18px}.feedback-form .support-ticket-field{gap:5px}.feedback-form .support-ticket-field textarea{min-height:72px}.feedback-actions{position:sticky;z-index:2;bottom:0;flex:0 0 auto;margin:0;padding:14px 22px;border-top:1px solid var(--max-border);background:var(--max-surface)}.support-ticket-header{display:flex;gap:14px;align-items:center;padding:20px 22px;border-bottom:1px solid var(--max-border)}.support-ticket-header-icon{width:44px;height:44px;flex-basis:44px;border-radius:14px;font-size:19px}.support-ticket-header>div{min-width:0;flex:1}.support-ticket-header h2,.support-ticket-header p,.support-ticket-success h3,.support-ticket-success p{margin:0}.support-ticket-header h2{color:var(--max-support-text);font-size:19px;font-weight:600;line-height:1.3}.support-ticket-header p{margin-top:3px;color:var(--max-muted);font-size:13px;line-height:1.4}.support-ticket-close{display:inline-flex;width:38px;height:38px;flex:0 0 38px;align-items:center;justify-content:center;padding:0;appearance:none;border:0;border-radius:50%;color:var(--max-muted);background:transparent;font:inherit;cursor:pointer}.support-ticket-close:hover{color:var(--max-support-text);background:var(--max-surface-soft)}.support-ticket-form{min-height:0;overflow:visible;padding:22px}.support-ticket-fields{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:18px}.support-ticket-field{display:flex;min-width:0;flex-direction:column;gap:7px;color:var(--max-support-text);font-size:13px;font-weight:600}.support-ticket-field>span{display:flex;gap:5px;align-items:baseline}.support-ticket-field>span small{color:var(--max-muted);font-size:11px;font-weight:400}.support-ticket-field-wide{grid-column:1/-1}.support-ticket-field input,.support-ticket-field textarea{width:100%;min-height:44px;padding:10px 12px;border:1px solid var(--max-border);border-radius:10px;outline:0;color:var(--max-support-text);background:var(--max-surface);box-shadow:none;font:inherit;font-size:14px;font-weight:400;line-height:1.45}.support-ticket-field textarea{min-height:116px;resize:vertical}.support-ticket-field input[readonly],.support-ticket-field textarea[readonly]{color:color-mix(in srgb,var(--max-support-text) 82%,var(--max-muted));background:color-mix(in srgb,var(--max-muted) 6%,var(--max-surface));cursor:default}.support-ticket-field input::placeholder,.support-ticket-field textarea::placeholder{color:var(--max-muted);opacity:.82}.support-ticket-field input:focus,.support-ticket-field textarea:focus{border-color:var(--max-accent);box-shadow:0 0 0 3px color-mix(in srgb,var(--max-accent) 13%,transparent)}:host ::ng-deep .support-ticket-dialog .p-select,:host ::ng-deep .support-ticket-dialog .p-multiselect{min-height:44px;border-color:var(--max-border);border-radius:10px;color:var(--max-support-text);background:var(--max-surface);box-shadow:none;font:inherit;font-size:14px;font-weight:400}:host ::ng-deep .support-ticket-dialog .p-select:not(.p-disabled).p-focus,:host ::ng-deep .support-ticket-dialog .p-multiselect:not(.p-disabled).p-focus{border-color:var(--max-accent);box-shadow:0 0 0 3px color-mix(in srgb,var(--max-accent) 13%,transparent)}:host ::ng-deep .support-ticket-dialog .p-select-label,:host ::ng-deep .support-ticket-dialog .p-multiselect-label,:host ::ng-deep .support-ticket-dialog .p-select-dropdown,:host ::ng-deep .support-ticket-dialog .p-multiselect-dropdown{color:var(--max-support-text);font:inherit;font-size:14px}:host ::ng-deep .support-ticket-dialog .p-select-label,:host ::ng-deep .support-ticket-dialog .p-multiselect-label{display:flex;min-height:42px;align-items:center}:host ::ng-deep .support-ticket-dialog .p-multiselect-label{flex-wrap:wrap;gap:5px;padding-block:5px}:host ::ng-deep .support-selected-tags{display:inline-flex;min-width:0;flex-wrap:wrap;gap:5px;align-items:center}:host ::ng-deep .support-ticket-dialog .p-tag{font-size:12px;font-weight:600}:host ::ng-deep .support-ticket-dialog .support-severity-tag,:host ::ng-deep .support-ticket-dialog .support-severity-option{color:#fff;background:var(--support-severity-color)}:host ::ng-deep .support-ticket-dialog .p-tag-icon{font-size:11px}:host ::ng-deep .support-ticket-dialog .p-select-option,:host ::ng-deep .support-ticket-dialog .p-multiselect-option{color:var(--max-support-text)}:host ::ng-deep .support-ticket-dialog .p-select-overlay,:host ::ng-deep .support-ticket-dialog .p-multiselect-overlay{border-color:var(--max-border);border-radius:12px;color:var(--max-support-text);background:var(--max-surface);box-shadow:0 12px 32px #1f1f1f2e;font:inherit}.support-ticket-notice,.support-ticket-error{margin:16px 0 0;padding:10px 12px;border-radius:10px;font-size:13px;line-height:1.45}.support-ticket-notice{color:var(--max-warning);background:color-mix(in srgb,var(--max-warning) 9%,var(--max-surface))}.support-ticket-error{color:var(--max-danger);background:color-mix(in srgb,var(--max-danger) 8%,var(--max-surface))}.support-ticket-actions{display:flex;gap:10px;justify-content:flex-end;margin-top:22px}.support-ticket-success,.support-ticket-error-page{display:flex;min-height:340px;align-items:center;justify-content:center;padding:38px 24px;flex-direction:column;text-align:center}.support-ticket-error-icon{display:inline-flex;width:64px;height:64px;align-items:center;justify-content:center;border-radius:50%;color:var(--max-danger);background:color-mix(in srgb,var(--max-danger) 12%,var(--max-surface))}.support-ticket-error-icon i,.support-ticket-success-icon i{font-size:40px}.support-ticket-error-page h3{margin:18px 0 0;color:var(--max-support-text);font-size:21px}.support-ticket-error-page p{max-width:420px;margin:7px 0 22px;color:var(--max-muted);font-size:14px;line-height:1.5}.support-ticket-success-icon{width:64px;height:64px;flex-basis:64px;border-radius:50%;color:var(--max-success);background:color-mix(in srgb,var(--max-success) 12%,var(--max-surface))}.support-ticket-success>button{margin-top:1rem}.support-ticket-close i{font-size:20px}.support-ticket-success h3{margin-top:18px;color:var(--max-support-text);font-size:21px}.support-ticket-success p{max-width:420px;margin-top:7px;color:var(--max-muted);font-size:14px;line-height:1.5;white-space:pre-line}.support-ticket-reference{display:flex;gap:6px;align-items:center;margin:22px 0;padding:10px 14px;border:1px solid var(--max-border);border-radius:10px;background:var(--max-surface-soft);font-size:13px}.support-ticket-reference span{color:var(--max-muted)}@keyframes max-thinking{0%{opacity:.55;transform:rotate(-8deg) scale(.86)}to{opacity:1;transform:rotate(8deg) scale(1)}}@media (prefers-reduced-motion: reduce){.message.streaming:before{animation:none}.suggestion-chip,.capability-option-card,.support-welcome-card{transition:none}}@media (max-width: 900px){.assistant-messages{padding-top:34px}}@media (max-width: 640px){.assistant-panel{grid-template-rows:64px minmax(0,1fr) auto}.assistant-header{padding:0 14px}.assistant-subtitle{display:none}.assistant-messages{padding:26px 18px 20px}.message.welcome{padding-top:24px}.message.welcome .suggestions,.assistant-cards,.assistant-visualisations,.capability-option-grid{grid-template-columns:1fr}.message.welcome .suggestion-chip{min-height:60px}.message.user{max-width:88%}.assistant-composer{width:100%;margin-bottom:12px}.assistant-footer{width:calc(100% - 24px)}.support-ticket-overlay{align-items:start;padding:10px}.support-ticket-dialog{max-height:none;border-radius:16px}.feedback-dialog{max-height:calc(100% - 20px)}.support-ticket-header{padding:16px}.support-ticket-header p{display:none}.feedback-header p{display:block}.feedback-form-body{padding:14px 16px}.feedback-actions{padding:12px 16px}.support-ticket-form{overflow:visible;padding:16px}.support-ticket-fields{grid-template-columns:1fr;gap:14px}.support-ticket-field-wide{grid-column:auto}.support-ticket-actions{flex-direction:column-reverse}.support-ticket-actions button{width:100%}}\n"] }]
|
|
1637
1896
|
}], ctorParameters: () => [{ type: MaxAssistantService }, { type: MaxAssistantExportService }, { type: MaxAssistantFeedbackService }, { type: MaxAssistantSupportService }, { type: i0.DestroyRef }, { type: undefined, decorators: [{
|
|
1638
1897
|
type: Inject,
|
|
1639
1898
|
args: [MAX_ASSISTANT_CONFIG]
|