@praxisui/ai 9.0.0-beta.84 → 9.0.0-beta.86
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/README.md +1 -1
- package/ai/component-registry.json +2 -2
- package/fesm2022/praxisui-ai.mjs +335 -160
- package/package.json +2 -2
- package/types/praxisui-ai.d.ts +43 -5
package/fesm2022/praxisui-ai.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { Component, Injectable, InjectionToken, Optional, Inject, inject, signal, computed, ChangeDetectorRef, ElementRef, ViewChild, Input, ChangeDetectionStrategy, EventEmitter, Injector, HostListener, Output, booleanAttribute } from '@angular/core';
|
|
3
3
|
import { SchemaType, GoogleGenerativeAI } from '@google/generative-ai';
|
|
4
|
-
import { throwError, from, Observable, of, defer, switchMap, Subject, tap, map as map$1, finalize, share, filter as filter$1, concat, merge, catchError as catchError$1, EMPTY, timer, takeUntil, timeout, take as take$1, BehaviorSubject, isObservable
|
|
4
|
+
import { throwError, from, Observable, of, firstValueFrom, defer, switchMap, Subject, tap, map as map$1, finalize, share, filter as filter$1, concat, merge, catchError as catchError$1, EMPTY, timer, takeUntil, timeout, take as take$1, BehaviorSubject, isObservable } from 'rxjs';
|
|
5
5
|
import { map, catchError, filter, take } from 'rxjs/operators';
|
|
6
6
|
import { HttpClient, HttpParams, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
|
|
7
|
-
import { API_URL, LoggerService, PraxisRuntimeComponentObservationRegistryService } from '@praxisui/core';
|
|
7
|
+
import { API_URL, LoggerService, PraxisRuntimeComponentObservationRegistryService, PraxisIconButtonComponent } from '@praxisui/core';
|
|
8
8
|
import * as i1$3 from '@angular/common';
|
|
9
9
|
import { NgTemplateOutlet, DatePipe, JsonPipe, CommonModule } from '@angular/common';
|
|
10
10
|
import * as i3 from '@angular/forms';
|
|
@@ -403,7 +403,7 @@ function toPraxisAssistantConversationMessageRole(role) {
|
|
|
403
403
|
* Do not edit manually. Run praxis-config-starter/tools/contracts/generate-ai-contract-bindings.js.
|
|
404
404
|
*/
|
|
405
405
|
const AI_CONTRACT_VERSION = 'v1.1';
|
|
406
|
-
const AI_CONTRACT_SCHEMA_HASH = '
|
|
406
|
+
const AI_CONTRACT_SCHEMA_HASH = 'f991cfb03ef0f6a283505c034a7afe40fbb089fb254d3a9251a5c35848d0a2b5';
|
|
407
407
|
const AI_STREAM_EVENT_SCHEMA_VERSION = 'v1';
|
|
408
408
|
const AI_DOMAIN_CATALOG_CONTEXT_HINT_SCHEMA_VERSION = 'praxis.ai.context-hints.domain-catalog/v0.2';
|
|
409
409
|
const AI_STREAM_EVENT_TYPES = ['status', 'thought.step', 'heartbeat', 'intent.resolved', 'result', 'error', 'cancelled'];
|
|
@@ -1451,6 +1451,14 @@ class AiBackendApiService {
|
|
|
1451
1451
|
getAiStatus() {
|
|
1452
1452
|
return this.http.get(`${this.aiBaseUrl()}/status`, { headers: this.buildHeaders() });
|
|
1453
1453
|
}
|
|
1454
|
+
transcribeAudio(audio, fileName, language) {
|
|
1455
|
+
const body = new FormData();
|
|
1456
|
+
body.append('audio', audio, fileName);
|
|
1457
|
+
if (language?.trim()) {
|
|
1458
|
+
body.append('language', language.trim());
|
|
1459
|
+
}
|
|
1460
|
+
return this.http.post(`${this.aiBaseUrl()}/transcriptions`, body, { headers: this.buildHeaders(), withCredentials: true });
|
|
1461
|
+
}
|
|
1454
1462
|
getAiContext(componentId, componentType) {
|
|
1455
1463
|
const params = new HttpParams({ fromObject: { componentType } });
|
|
1456
1464
|
return this.http.get(`${this.aiContextBaseUrl()}/${componentId}`, { headers: this.buildHeaders(), params });
|
|
@@ -1777,6 +1785,230 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
1777
1785
|
args: [{ providedIn: 'root' }]
|
|
1778
1786
|
}] });
|
|
1779
1787
|
|
|
1788
|
+
class PraxisBrowserSpeechTranscriptionError extends Error {
|
|
1789
|
+
code;
|
|
1790
|
+
constructor(code, message) {
|
|
1791
|
+
super(message);
|
|
1792
|
+
this.code = code;
|
|
1793
|
+
this.name = 'PraxisBrowserSpeechTranscriptionError';
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
1796
|
+
class PraxisBrowserSpeechTranscriptionService {
|
|
1797
|
+
activeRecognition = null;
|
|
1798
|
+
isSupported() {
|
|
1799
|
+
return this.resolveCtor() !== null;
|
|
1800
|
+
}
|
|
1801
|
+
transcribe(options = {}) {
|
|
1802
|
+
const RecognitionCtor = this.resolveCtor();
|
|
1803
|
+
if (!RecognitionCtor) {
|
|
1804
|
+
return Promise.reject(new PraxisBrowserSpeechTranscriptionError('unsupported', 'Browser speech recognition is not supported.'));
|
|
1805
|
+
}
|
|
1806
|
+
this.cancel();
|
|
1807
|
+
const recognition = new RecognitionCtor();
|
|
1808
|
+
recognition.lang = options.lang?.trim() || this.resolveNavigatorLanguage();
|
|
1809
|
+
recognition.continuous = false;
|
|
1810
|
+
recognition.interimResults = false;
|
|
1811
|
+
recognition.maxAlternatives = 1;
|
|
1812
|
+
this.activeRecognition = recognition;
|
|
1813
|
+
return new Promise((resolve, reject) => {
|
|
1814
|
+
let transcript = '';
|
|
1815
|
+
let failed = false;
|
|
1816
|
+
const cleanup = () => {
|
|
1817
|
+
if (this.activeRecognition === recognition) {
|
|
1818
|
+
this.activeRecognition = null;
|
|
1819
|
+
}
|
|
1820
|
+
recognition.onresult = null;
|
|
1821
|
+
recognition.onerror = null;
|
|
1822
|
+
recognition.onend = null;
|
|
1823
|
+
};
|
|
1824
|
+
recognition.onresult = (event) => {
|
|
1825
|
+
transcript = this.extractTranscript(event).trim();
|
|
1826
|
+
};
|
|
1827
|
+
recognition.onerror = (event) => {
|
|
1828
|
+
failed = true;
|
|
1829
|
+
cleanup();
|
|
1830
|
+
reject(this.toTranscriptionError(event));
|
|
1831
|
+
};
|
|
1832
|
+
recognition.onend = () => {
|
|
1833
|
+
cleanup();
|
|
1834
|
+
if (failed) {
|
|
1835
|
+
return;
|
|
1836
|
+
}
|
|
1837
|
+
if (!transcript) {
|
|
1838
|
+
reject(new PraxisBrowserSpeechTranscriptionError('no-speech', 'No speech was recognized.'));
|
|
1839
|
+
return;
|
|
1840
|
+
}
|
|
1841
|
+
resolve({
|
|
1842
|
+
text: transcript,
|
|
1843
|
+
language: recognition.lang,
|
|
1844
|
+
});
|
|
1845
|
+
};
|
|
1846
|
+
try {
|
|
1847
|
+
recognition.start();
|
|
1848
|
+
}
|
|
1849
|
+
catch (error) {
|
|
1850
|
+
cleanup();
|
|
1851
|
+
reject(new PraxisBrowserSpeechTranscriptionError('error', error instanceof Error ? error.message : 'Failed to start browser speech recognition.'));
|
|
1852
|
+
}
|
|
1853
|
+
});
|
|
1854
|
+
}
|
|
1855
|
+
stop() {
|
|
1856
|
+
this.activeRecognition?.stop();
|
|
1857
|
+
}
|
|
1858
|
+
cancel() {
|
|
1859
|
+
this.activeRecognition?.abort();
|
|
1860
|
+
this.activeRecognition = null;
|
|
1861
|
+
}
|
|
1862
|
+
extractTranscript(event) {
|
|
1863
|
+
const segments = [];
|
|
1864
|
+
for (let resultIndex = 0; resultIndex < event.results.length; resultIndex++) {
|
|
1865
|
+
const result = event.results[resultIndex] ?? event.results.item(resultIndex);
|
|
1866
|
+
if (!result?.length) {
|
|
1867
|
+
continue;
|
|
1868
|
+
}
|
|
1869
|
+
const alternative = result[0] ?? result.item(0);
|
|
1870
|
+
const text = alternative?.transcript?.trim();
|
|
1871
|
+
if (text) {
|
|
1872
|
+
segments.push(text);
|
|
1873
|
+
}
|
|
1874
|
+
}
|
|
1875
|
+
return segments.join(' ');
|
|
1876
|
+
}
|
|
1877
|
+
toTranscriptionError(event) {
|
|
1878
|
+
const error = (event.error || '').toLowerCase();
|
|
1879
|
+
if (error === 'not-allowed' || error === 'service-not-allowed') {
|
|
1880
|
+
return new PraxisBrowserSpeechTranscriptionError('permission-denied', event.message || 'Browser microphone permission was denied.');
|
|
1881
|
+
}
|
|
1882
|
+
if (error === 'no-speech') {
|
|
1883
|
+
return new PraxisBrowserSpeechTranscriptionError('no-speech', event.message || 'No speech was recognized.');
|
|
1884
|
+
}
|
|
1885
|
+
if (error === 'aborted') {
|
|
1886
|
+
return new PraxisBrowserSpeechTranscriptionError('aborted', event.message || 'Browser speech recognition was aborted.');
|
|
1887
|
+
}
|
|
1888
|
+
return new PraxisBrowserSpeechTranscriptionError('error', event.message || 'Browser speech recognition failed.');
|
|
1889
|
+
}
|
|
1890
|
+
resolveCtor() {
|
|
1891
|
+
if (typeof window === 'undefined') {
|
|
1892
|
+
return null;
|
|
1893
|
+
}
|
|
1894
|
+
const speechWindow = window;
|
|
1895
|
+
return speechWindow.SpeechRecognition ?? speechWindow.webkitSpeechRecognition ?? null;
|
|
1896
|
+
}
|
|
1897
|
+
resolveNavigatorLanguage() {
|
|
1898
|
+
if (typeof navigator !== 'undefined' && navigator.language?.trim()) {
|
|
1899
|
+
return navigator.language.trim();
|
|
1900
|
+
}
|
|
1901
|
+
return 'pt-BR';
|
|
1902
|
+
}
|
|
1903
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisBrowserSpeechTranscriptionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1904
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisBrowserSpeechTranscriptionService, providedIn: 'root' });
|
|
1905
|
+
}
|
|
1906
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisBrowserSpeechTranscriptionService, decorators: [{
|
|
1907
|
+
type: Injectable,
|
|
1908
|
+
args: [{ providedIn: 'root' }]
|
|
1909
|
+
}] });
|
|
1910
|
+
|
|
1911
|
+
class PraxisGovernedAudioTranscriptionService {
|
|
1912
|
+
backend = inject(AiBackendApiService);
|
|
1913
|
+
activeRecorder = null;
|
|
1914
|
+
activeStream = null;
|
|
1915
|
+
cancelled = false;
|
|
1916
|
+
isSupported() {
|
|
1917
|
+
return typeof navigator !== 'undefined'
|
|
1918
|
+
&& !!navigator.mediaDevices?.getUserMedia
|
|
1919
|
+
&& typeof MediaRecorder !== 'undefined';
|
|
1920
|
+
}
|
|
1921
|
+
async transcribe(options = {}) {
|
|
1922
|
+
if (!this.isSupported()) {
|
|
1923
|
+
throw new PraxisBrowserSpeechTranscriptionError('unsupported', 'Audio capture is not supported.');
|
|
1924
|
+
}
|
|
1925
|
+
this.cancel();
|
|
1926
|
+
this.cancelled = false;
|
|
1927
|
+
let stream;
|
|
1928
|
+
try {
|
|
1929
|
+
stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
1930
|
+
}
|
|
1931
|
+
catch (error) {
|
|
1932
|
+
throw new PraxisBrowserSpeechTranscriptionError('permission-denied', error instanceof Error ? error.message : 'Microphone permission was denied.');
|
|
1933
|
+
}
|
|
1934
|
+
this.activeStream = stream;
|
|
1935
|
+
const mimeType = this.resolveMimeType();
|
|
1936
|
+
const recorder = mimeType ? new MediaRecorder(stream, { mimeType }) : new MediaRecorder(stream);
|
|
1937
|
+
this.activeRecorder = recorder;
|
|
1938
|
+
const chunks = [];
|
|
1939
|
+
return new Promise((resolve, reject) => {
|
|
1940
|
+
recorder.ondataavailable = (event) => {
|
|
1941
|
+
if (event.data.size > 0)
|
|
1942
|
+
chunks.push(event.data);
|
|
1943
|
+
};
|
|
1944
|
+
recorder.onerror = () => {
|
|
1945
|
+
this.cleanup(recorder, stream);
|
|
1946
|
+
reject(new PraxisBrowserSpeechTranscriptionError('error', 'Audio capture failed.'));
|
|
1947
|
+
};
|
|
1948
|
+
recorder.onstop = () => {
|
|
1949
|
+
const cancelled = this.cancelled;
|
|
1950
|
+
this.cleanup(recorder, stream);
|
|
1951
|
+
if (cancelled) {
|
|
1952
|
+
reject(new PraxisBrowserSpeechTranscriptionError('aborted', 'Audio capture was cancelled.'));
|
|
1953
|
+
return;
|
|
1954
|
+
}
|
|
1955
|
+
const audio = new Blob(chunks, { type: recorder.mimeType || mimeType || 'audio/webm' });
|
|
1956
|
+
if (!audio.size) {
|
|
1957
|
+
reject(new PraxisBrowserSpeechTranscriptionError('no-speech', 'No audio was captured.'));
|
|
1958
|
+
return;
|
|
1959
|
+
}
|
|
1960
|
+
const extension = audio.type.includes('mp4') ? 'm4a' : audio.type.includes('ogg') ? 'ogg' : 'webm';
|
|
1961
|
+
void firstValueFrom(this.backend.transcribeAudio(audio, `praxis-voice.${extension}`, options.lang))
|
|
1962
|
+
.then((response) => {
|
|
1963
|
+
if (!response.text?.trim()) {
|
|
1964
|
+
throw new PraxisBrowserSpeechTranscriptionError('no-speech', 'No speech was recognized.');
|
|
1965
|
+
}
|
|
1966
|
+
resolve({ text: response.text.trim(), language: response.language ?? options.lang });
|
|
1967
|
+
})
|
|
1968
|
+
.catch((error) => reject(error instanceof PraxisBrowserSpeechTranscriptionError
|
|
1969
|
+
? error
|
|
1970
|
+
: new PraxisBrowserSpeechTranscriptionError('error', 'Governed transcription failed.')));
|
|
1971
|
+
};
|
|
1972
|
+
recorder.start();
|
|
1973
|
+
});
|
|
1974
|
+
}
|
|
1975
|
+
stop() {
|
|
1976
|
+
if (this.activeRecorder?.state === 'recording')
|
|
1977
|
+
this.activeRecorder.stop();
|
|
1978
|
+
}
|
|
1979
|
+
cancel() {
|
|
1980
|
+
this.cancelled = true;
|
|
1981
|
+
if (this.activeRecorder?.state === 'recording')
|
|
1982
|
+
this.activeRecorder.stop();
|
|
1983
|
+
this.stopTracks(this.activeStream);
|
|
1984
|
+
this.activeRecorder = null;
|
|
1985
|
+
this.activeStream = null;
|
|
1986
|
+
}
|
|
1987
|
+
resolveMimeType() {
|
|
1988
|
+
return ['audio/mp4', 'audio/webm;codecs=opus', 'audio/webm', 'audio/ogg;codecs=opus']
|
|
1989
|
+
.find((type) => MediaRecorder.isTypeSupported(type)) ?? '';
|
|
1990
|
+
}
|
|
1991
|
+
cleanup(recorder, stream) {
|
|
1992
|
+
recorder.ondataavailable = null;
|
|
1993
|
+
recorder.onerror = null;
|
|
1994
|
+
recorder.onstop = null;
|
|
1995
|
+
this.stopTracks(stream);
|
|
1996
|
+
if (this.activeRecorder === recorder)
|
|
1997
|
+
this.activeRecorder = null;
|
|
1998
|
+
if (this.activeStream === stream)
|
|
1999
|
+
this.activeStream = null;
|
|
2000
|
+
}
|
|
2001
|
+
stopTracks(stream) {
|
|
2002
|
+
stream?.getTracks().forEach((track) => track.stop());
|
|
2003
|
+
}
|
|
2004
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisGovernedAudioTranscriptionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2005
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisGovernedAudioTranscriptionService, providedIn: 'root' });
|
|
2006
|
+
}
|
|
2007
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisGovernedAudioTranscriptionService, decorators: [{
|
|
2008
|
+
type: Injectable,
|
|
2009
|
+
args: [{ providedIn: 'root' }]
|
|
2010
|
+
}] });
|
|
2011
|
+
|
|
1780
2012
|
class AgenticAuthoringTurnClientService {
|
|
1781
2013
|
aiApi = inject(AiBackendApiService);
|
|
1782
2014
|
logger = inject(LoggerService, { optional: true });
|
|
@@ -2940,6 +3172,9 @@ class PraxisAssistantTurnController {
|
|
|
2940
3172
|
}
|
|
2941
3173
|
const current = this.stateSubject.value;
|
|
2942
3174
|
const effectiveAction = this.resolveSubmitAction(action, current);
|
|
3175
|
+
const pendingClarification = current.state === 'clarification'
|
|
3176
|
+
? current.pendingClarification
|
|
3177
|
+
: undefined;
|
|
2943
3178
|
const clientTurnId = this.createId('turn');
|
|
2944
3179
|
const displayPrompt = typeof effectiveAction.displayPrompt === 'string'
|
|
2945
3180
|
? effectiveAction.displayPrompt.trim()
|
|
@@ -2956,7 +3191,7 @@ class PraxisAssistantTurnController {
|
|
|
2956
3191
|
prompt: normalized,
|
|
2957
3192
|
action: effectiveAction,
|
|
2958
3193
|
phase: 'contextualize',
|
|
2959
|
-
pendingClarification
|
|
3194
|
+
pendingClarification,
|
|
2960
3195
|
});
|
|
2961
3196
|
}
|
|
2962
3197
|
answerClarification(option) {
|
|
@@ -3440,7 +3675,13 @@ function toPraxisAssistantClarificationOption(reply) {
|
|
|
3440
3675
|
function submitPraxisAssistantQuickReply(controller, reply) {
|
|
3441
3676
|
const state = controller.snapshot();
|
|
3442
3677
|
const prompt = canonicalQuickReplyPrompt(reply);
|
|
3443
|
-
const
|
|
3678
|
+
const semanticDecision = cloneRecord(reply.semanticDecision);
|
|
3679
|
+
const canonicalAction = cloneRecord(reply.canonicalAction);
|
|
3680
|
+
const contextHints = {
|
|
3681
|
+
...(cloneRecord(reply.contextHints) ?? {}),
|
|
3682
|
+
...(canonicalAction ? { canonicalAction } : {}),
|
|
3683
|
+
...(semanticDecision ? { semanticDecision } : {}),
|
|
3684
|
+
};
|
|
3444
3685
|
if (state.state === 'clarification') {
|
|
3445
3686
|
return controller.answerClarification(toPraxisAssistantClarificationOption(reply));
|
|
3446
3687
|
}
|
|
@@ -3449,7 +3690,8 @@ function submitPraxisAssistantQuickReply(controller, reply) {
|
|
|
3449
3690
|
id: reply.id,
|
|
3450
3691
|
value: cloneValue(reply.value) ?? prompt,
|
|
3451
3692
|
displayPrompt: reply.label,
|
|
3452
|
-
contextHints,
|
|
3693
|
+
contextHints: Object.keys(contextHints).length ? contextHints : undefined,
|
|
3694
|
+
activeSemanticDecision: semanticDecision,
|
|
3453
3695
|
});
|
|
3454
3696
|
}
|
|
3455
3697
|
function canonicalQuickReplyPrompt(reply) {
|
|
@@ -7739,7 +7981,7 @@ class PraxisAiAssistantComponent {
|
|
|
7739
7981
|
return 'Erro ao comunicar com a IA. Tente novamente.';
|
|
7740
7982
|
}
|
|
7741
7983
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisAiAssistantComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
7742
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PraxisAiAssistantComponent, isStandalone: true, selector: "praxis-ai-assistant", inputs: { adapter: "adapter", riskPolicy: "riskPolicy", allowManualPatchEdit: "allowManualPatchEdit", hasBackdrop: "hasBackdrop" }, viewQueries: [{ propertyName: "overlayOrigin", first: true, predicate: CdkOverlayOrigin, descendants: true }, { propertyName: "triggerButton", first: true, predicate: ["triggerBtn"], descendants: true, read: ElementRef }, { propertyName: "inputElement", first: true, predicate: ["inputEl"], descendants: true }], ngImport: i0, template: "<!-- Trigger Button -->\n<button\n mat-icon-button\n cdkOverlayOrigin\n #trigger=\"cdkOverlayOrigin\"\n #triggerBtn\n (click)=\"open()\"\n [disabled]=\"isOpen\"\n class=\"ai-trigger-btn\"\n matTooltip=\"Assistente de Configura\u00E7\u00E3o\"\n aria-label=\"Abrir Assistente IA\">\n <mat-icon>auto_awesome</mat-icon>\n</button>\n\n<!-- Overlay Template -->\n<ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"trigger\"\n [cdkConnectedOverlayOpen]=\"isOpen\"\n [cdkConnectedOverlayHasBackdrop]=\"hasBackdrop\"\n [cdkConnectedOverlayPositions]=\"overlayPositions\"\n [cdkConnectedOverlayPush]=\"true\"\n [cdkConnectedOverlayViewportMargin]=\"12\"\n cdkConnectedOverlayPanelClass=\"ai-assistant-overlay-pane\"\n cdkConnectedOverlayBackdropClass=\"ai-assistant-backdrop\"\n (backdropClick)=\"close()\"\n (overlayOutsideClick)=\"close()\"\n (detach)=\"close()\">\n\n <div\n class=\"ai-assistant-panel\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"Assistente de Configura\u00E7\u00E3o\"\n [attr.aria-busy]=\"isBusyState() ? 'true' : null\"\n [cdkTrapFocus]=\"hasBackdrop\"\n [cdkTrapFocusAutoCapture]=\"hasBackdrop\"\n (keydown)=\"onKeydown($event)\"\n >\n\n <!-- HEADER -->\n <div class=\"assistant-header\">\n <div class=\"assistant-header__left\">\n <mat-icon class=\"magic-icon\">auto_awesome</mat-icon>\n <div class=\"assistant-title-group\">\n <div class=\"assistant-title\">Assistente de Configura\u00E7\u00E3o</div>\n <div class=\"assistant-subtitle\">Copiloto contextual para ajustes guiados</div>\n <div class=\"assistant-header-chips\">\n <span\n class=\"mode-chip\"\n [class.mock]=\"mockMode\"\n [matTooltip]=\"mockMode ? 'Sem chave de API: respostas de demonstra\u00E7\u00E3o' : 'Conectado ao assistente configurado'\"\n >\n {{ mockMode ? 'Mock' : 'Conectado' }}\n </span>\n <span\n class=\"policy-chip\"\n [class.strict]=\"isStrictRiskPolicy()\"\n [matTooltip]=\"getRiskPolicyTooltip()\"\n >\n {{ getRiskPolicyLabel() }}\n </span>\n </div>\n </div>\n </div>\n <div class=\"assistant-header__right\">\n <button\n mat-icon-button\n type=\"button\"\n class=\"assistant-close-btn\"\n (click)=\"close()\"\n aria-label=\"Fechar assistente\"\n matTooltip=\"Fechar assistente\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </div>\n </div>\n <div\n class=\"assistant-status\"\n [class.processing]=\"isBusyState()\"\n [class.pending]=\"state === 'clarification'\"\n [class.warning]=\"state === 'error'\"\n [class.success]=\"state === 'review' || state === 'success'\"\n [class.compact]=\"!shouldShowSystemStatusDetail()\"\n role=\"status\"\n [attr.aria-live]=\"getSystemStatusAriaLive()\"\n aria-atomic=\"true\"\n >\n <span class=\"assistant-status-dot\" aria-hidden=\"true\"></span>\n <div class=\"assistant-status-content\">\n <div class=\"assistant-status-label\">\n <span class=\"assistant-status-label-prefix\">Status:</span>\n <span>{{ getSystemStatusLabel() }}</span>\n @if (shouldShowSnapshotFallbackBadge()) {\n <span class=\"assistant-status-mode\">Snapshot</span>\n }\n </div>\n @if (shouldShowSystemStatusDetail()) {\n <div class=\"assistant-status-detail\">{{ getSystemStatusDetail() }}</div>\n }\n </div>\n </div>\n @if (shouldShowTaskFlow()) {\n <div class=\"assistant-flow\" role=\"list\" aria-label=\"Fluxo da proposta\">\n @for (step of flowSteps; track step) {\n <div\n class=\"flow-step\"\n role=\"listitem\"\n [class.active]=\"getFlowStepState(step.step) === 'active'\"\n [class.done]=\"getFlowStepState(step.step) === 'done'\"\n >\n <span class=\"flow-step-index\">{{ step.step }}</span>\n <span class=\"flow-step-content\">\n <span class=\"flow-step-label\">{{ step.label }}</span>\n <span class=\"flow-step-detail\">{{ getFlowStepDetail(step.step) }}</span>\n </span>\n </div>\n }\n </div>\n }\n <div class=\"assistant-nav\">\n <div\n class=\"assistant-tabs\"\n role=\"tablist\"\n aria-label=\"Se\u00E7\u00F5es do assistente\"\n (keydown)=\"onTabsKeydown($event)\"\n >\n @if (isTaskMode()) {\n <button\n class=\"assistant-tab\"\n type=\"button\"\n id=\"assistant-tab-task\"\n role=\"tab\"\n aria-label=\"Proposta atual\"\n [attr.aria-selected]=\"isActiveTab('task')\"\n aria-controls=\"assistant-panel-task\"\n [attr.tabindex]=\"isActiveTab('task') ? 0 : -1\"\n [class.active]=\"isActiveTab('task')\"\n (click)=\"setActiveTab('task')\"\n >\n Proposta\n @if (hasPendingClarification() && !isActiveTab('task')) {\n <span class=\"assistant-tab-badge\">1</span>\n }\n </button>\n }\n <button\n class=\"assistant-tab\"\n type=\"button\"\n id=\"assistant-tab-chat\"\n role=\"tab\"\n aria-label=\"Hist\u00F3rico\"\n [attr.aria-selected]=\"isActiveTab('chat')\"\n aria-controls=\"assistant-panel-chat\"\n [attr.tabindex]=\"isActiveTab('chat') ? 0 : -1\"\n [class.active]=\"isActiveTab('chat')\"\n (click)=\"setActiveTab('chat')\"\n >\n Hist\u00F3rico\n </button>\n <button\n class=\"assistant-tab\"\n type=\"button\"\n id=\"assistant-tab-suggestions\"\n role=\"tab\"\n aria-label=\"Sugest\u00F5es de melhoria\"\n [attr.aria-selected]=\"isActiveTab('suggestions')\"\n aria-controls=\"assistant-panel-suggestions\"\n [attr.tabindex]=\"isActiveTab('suggestions') ? 0 : -1\"\n [class.active]=\"isActiveTab('suggestions')\"\n (click)=\"setActiveTab('suggestions')\"\n >\n Sugest\u00F5es\n </button>\n </div>\n </div>\n\n <!-- BODY: Dynamic Content based on State -->\n <div class=\"assistant-body\">\n @if (shouldShowThoughtCard()) {\n <div class=\"assistant-thought assistant-section\">\n <div class=\"assistant-thought-meta\">\n <mat-icon>psychology</mat-icon>\n <span>{{ getThoughtTimingLabel() }}</span>\n </div>\n <div class=\"assistant-thought-summary\">{{ getThoughtSummary() }}</div>\n <div class=\"assistant-thought-plan\">\n <div class=\"assistant-thought-plan-title\">{{ getThoughtPlanTitle() }}</div>\n <div class=\"assistant-thought-plan-actions\">\n <button\n mat-stroked-button\n type=\"button\"\n class=\"thought-action-details\"\n (click)=\"openThoughtDetails()\"\n [attr.aria-label]=\"getThoughtDetailsLabel()\"\n [matTooltip]=\"getThoughtDetailsTooltip()\"\n >\n {{ getThoughtDetailsLabel() }}\n </button>\n @if (shouldShowThoughtPreviewAction()) {\n <button\n mat-flat-button\n color=\"primary\"\n type=\"button\"\n class=\"thought-action-preview\"\n (click)=\"openThoughtPreview()\"\n [matTooltip]=\"getThoughtPreviewTooltip()\"\n >\n Pr\u00E9via\n </button>\n }\n </div>\n <div class=\"assistant-thought-plan-hint\">{{ getThoughtActionHint() }}</div>\n @if (getThoughtChecklist(); as thoughtChecklist) {\n @if (thoughtChecklist.length) {\n <div class=\"assistant-thought-checklist\">\n @for (item of thoughtChecklist; track item) {\n <div class=\"assistant-thought-checklist-item\">\n <mat-icon>radio_button_unchecked</mat-icon>\n <span>{{ item }}</span>\n </div>\n }\n </div>\n }\n @if (isBusyState() && !thoughtChecklist.length) {\n <div class=\"assistant-thought-shimmer\">\n <div class=\"shimmer-line shimmer-line-1\"></div>\n <div class=\"shimmer-line shimmer-line-2\"></div>\n <div class=\"shimmer-line shimmer-line-3\"></div>\n </div>\n }\n }\n </div>\n </div>\n }\n @if (processingInfoVisible) {\n <div class=\"processing-banner\">\n <mat-spinner diameter=\"16\"></mat-spinner>\n <span>{{ aiExplanation || 'Analisando solicita\u00E7\u00E3o e preparando proposta...' }}</span>\n <button mat-button type=\"button\" class=\"processing-retry\" (click)=\"retryProcessing()\">Tentar novamente</button>\n </div>\n }\n @if (historyContext && isActiveTab('chat')) {\n <div\n class=\"assistant-history assistant-section\"\n id=\"assistant-panel-chat\"\n role=\"tabpanel\"\n aria-labelledby=\"assistant-tab-chat\"\n >\n <div class=\"section-header\">\n <div class=\"section-heading\">\n <div class=\"section-title\">Hist\u00F3rico</div>\n <div class=\"section-subtitle\">Sess\u00F5es recentes, pedidos reaproveit\u00E1veis e desfazer r\u00E1pido.</div>\n </div>\n <div class=\"history-actions\" role=\"group\" aria-label=\"A\u00E7\u00F5es do hist\u00F3rico\">\n <button\n mat-stroked-button\n type=\"button\"\n class=\"history-action-btn\"\n (click)=\"historyExpanded = !historyExpanded\"\n [matTooltip]=\"historyExpanded ? 'Recolher hist\u00F3rico' : 'Expandir hist\u00F3rico'\"\n [attr.aria-label]=\"historyExpanded ? 'Recolher hist\u00F3rico' : 'Expandir hist\u00F3rico'\"\n [disabled]=\"!historyWarnings.length && !historySessions.length && !activeHistoryMessages.length\"\n >\n <mat-icon>{{ historyExpanded ? 'expand_less' : 'expand_more' }}</mat-icon>\n <span>{{ historyExpanded ? 'Recolher' : 'Expandir' }}</span>\n </button>\n <button\n mat-stroked-button\n type=\"button\"\n class=\"history-action-btn\"\n (click)=\"startNewSession()\"\n matTooltip=\"Nova conversa\"\n aria-label=\"Nova conversa\"\n [disabled]=\"isBusyState()\"\n >\n <mat-icon>add_comment</mat-icon>\n <span>Nova conversa</span>\n </button>\n <button\n mat-stroked-button\n type=\"button\"\n (click)=\"clearHistory()\"\n matTooltip=\"Limpar hist\u00F3rico local\"\n aria-label=\"Limpar hist\u00F3rico local\"\n class=\"history-action-btn history-action-btn--danger\"\n [disabled]=\"!historySessions.length\"\n >\n <mat-icon>delete_outline</mat-icon>\n <span>Limpar</span>\n </button>\n </div>\n </div>\n @if (historyUndoDeleteSession) {\n <div class=\"history-undo\">\n <span>Sess\u00E3o removida.</span>\n <button mat-button type=\"button\" (click)=\"undoRemoveHistorySession()\">\n Desfazer\n </button>\n </div>\n }\n @if (historyExpanded && historyWarnings.length) {\n <div class=\"history-warnings\">\n <mat-icon>info</mat-icon>\n <div class=\"history-warnings-list\">\n @for (warning of historyWarnings; track warning) {\n <div>{{ warning }}</div>\n }\n <div class=\"history-warnings-hint\">\n Configure headers via API_CONFIG_STORAGE_OPTIONS no host.\n </div>\n </div>\n </div>\n }\n @if (historyExpanded && historySessions.length) {\n <div class=\"history-sessions\">\n @for (session of historySessions; track session.id) {\n <div\n class=\"history-session\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"selectHistorySession(session.id)\"\n (keydown)=\"onHistorySessionCardKeydown($event, session.id)\"\n [class.active]=\"session.id === activeHistorySession?.id\"\n [matTooltip]=\"getHistorySessionTooltip(session)\"\n [matTooltipDisabled]=\"!session.componentType && !session.componentId\"\n >\n <div class=\"history-session-main\">\n <span class=\"history-session-title\">{{ session.title }}</span>\n <div class=\"history-session-main-right\">\n <span class=\"history-session-time\">{{ session.updatedAt | date:'short' }}</span>\n <div class=\"history-session-tools\">\n <button\n mat-icon-button\n type=\"button\"\n class=\"history-session-tool\"\n (click)=\"reuseHistorySessionPrompt(session.id, $event)\"\n matTooltip=\"Reusar \u00FAltimo pedido\"\n aria-label=\"Reusar \u00FAltimo pedido\"\n >\n <mat-icon>edit_note</mat-icon>\n </button>\n <button\n mat-icon-button\n type=\"button\"\n class=\"history-session-tool history-session-tool--danger\"\n (click)=\"removeHistorySession(session.id, $event)\"\n matTooltip=\"Excluir sess\u00E3o\"\n aria-label=\"Excluir sess\u00E3o\"\n >\n <mat-icon>delete_outline</mat-icon>\n </button>\n </div>\n </div>\n </div>\n <div class=\"history-session-meta\">\n @if (session.componentType) {\n <span class=\"history-chip\">{{ session.componentType }}</span>\n }\n @if (session.componentId) {\n <span class=\"history-chip\">{{ session.componentId }}</span>\n }\n </div>\n </div>\n }\n </div>\n }\n @if (historyExpanded && !historySessions.length) {\n <div class=\"history-empty\">\n Nenhuma sess\u00E3o salva ainda.\n </div>\n }\n @if (historyExpanded && activeHistoryMessages.length) {\n <div class=\"history-messages\">\n @if (activeHistoryTotalMessages > activeHistoryMessages.length) {\n <div\n class=\"history-messages-hint\"\n >\n Mostrando \u00FAltimas {{ activeHistoryMessages.length }} de {{ activeHistoryTotalMessages }} mensagens.\n </div>\n }\n @for (msg of activeHistoryMessages; track msg.id) {\n <div\n class=\"history-message\"\n [class.user]=\"msg.role === 'user'\"\n [class.assistant]=\"msg.role === 'assistant'\"\n >\n <div class=\"history-message-header\">\n <span class=\"history-message-role\">{{ msg.role === 'user' ? 'Voc\u00EA' : 'Assistente' }}</span>\n <span class=\"history-message-time\">{{ msg.createdAt | date:'shortTime' }}</span>\n @if (msg.context?.usedRag) {\n <span\n class=\"history-rag\"\n matTooltip=\"Resposta baseada em contexto recuperado (RAG)\"\n >RAG</span>\n }\n </div>\n <div class=\"history-message-text\">{{ msg.text }}</div>\n </div>\n }\n </div>\n }\n @if (historyExpanded && historySessions.length && !activeHistoryMessages.length) {\n <div class=\"history-empty history-empty--panel\">\n Selecione uma sess\u00E3o para visualizar as mensagens.\n </div>\n }\n @if (historyExpanded) {\n <div class=\"history-helper\">\n O hist\u00F3rico \u00E9 local ao usu\u00E1rio e ao componente atual.\n </div>\n }\n </div>\n }\n\n @if (loadingSuggestions && isActiveTab('suggestions')) {\n <div\n class=\"loading-suggestions assistant-section\"\n id=\"assistant-panel-suggestions\"\n role=\"tabpanel\"\n aria-labelledby=\"assistant-tab-suggestions\"\n >\n <mat-spinner diameter=\"20\"></mat-spinner>\n <span>Carregando sugest\u00F5es de melhoria...</span>\n </div>\n }\n\n <!-- STATE: LISTENING (Suggestions) -->\n @if (state === 'listening' && isActiveTab('suggestions')) {\n <div\n class=\"suggestions-area assistant-section\"\n id=\"assistant-panel-suggestions\"\n role=\"tabpanel\"\n aria-labelledby=\"assistant-tab-suggestions\"\n >\n <div class=\"section-header\">\n <div class=\"section-title\">Sugest\u00F5es de melhoria</div>\n <div class=\"suggestions-actions\">\n <button mat-icon-button type=\"button\" (click)=\"refreshSuggestions()\" [disabled]=\"loadingSuggestions\" matTooltip=\"Atualizar sugest\u00F5es\">\n <mat-icon>refresh</mat-icon>\n </button>\n </div>\n </div>\n @if (!loadingSuggestions) {\n <div class=\"suggestions-hero\">\n <div class=\"suggestions-hero__label\">Contexto ativo</div>\n <div class=\"suggestions-hero__title\">{{ adapter.componentName || 'Componente atual' }}</div>\n <div class=\"suggestions-hero__detail\">{{ getSystemStatusDetail() }}</div>\n </div>\n }\n @if (suggestionsWarnings.length) {\n <div class=\"warnings-area\">\n <mat-icon class=\"warnings-icon\">warning_amber</mat-icon>\n <div class=\"warnings-content\">\n <div class=\"warnings-title\">Avisos</div>\n <div class=\"warnings-list\">\n @for (warning of suggestionsWarnings; track warning) {\n <div>{{ warning }}</div>\n }\n </div>\n </div>\n </div>\n }\n @if (!loadingSuggestions && (richSuggestions.length || hasDismissedSuggestions())) {\n <div class=\"suggestions-content\">\n @if (hasDismissedSuggestions()) {\n <div class=\"suggestions-filter\">\n <span>{{ getDismissedSuggestionCount() }} oculta(s)</span>\n <button mat-button type=\"button\" (click)=\"restoreDismissedSuggestions()\">\n Restaurar\n </button>\n </div>\n }\n @if (getVisibleSuggestions().length) {\n <div class=\"suggestions-list\">\n @for (sug of getVisibleSuggestions(); track sug.id) {\n <div\n class=\"suggestion-item\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'Selecionar sugest\u00E3o: ' + sug.label\"\n (click)=\"selectSuggestion(sug)\"\n (keydown)=\"onSuggestionCardKeydown($event, sug)\"\n >\n <div class=\"suggestion-copy\">\n <div class=\"suggestion-main\">\n @if (sug.icon) {\n <mat-icon class=\"suggestion-icon\">{{ sug.icon }}</mat-icon>\n }\n <span class=\"suggestion-label\">{{ sug.label }}</span>\n @if (sug.group) {\n <span class=\"suggestion-group\">{{ sug.group }}</span>\n }\n </div>\n @if (sug.description) {\n <div class=\"suggestion-desc\">{{ sug.description }}</div>\n }\n </div>\n <div class=\"suggestion-actions\">\n <span class=\"suggestion-arrow\" aria-hidden=\"true\">\n <mat-icon>chevron_right</mat-icon>\n </span>\n <button\n mat-icon-button\n type=\"button\"\n class=\"suggestion-action-btn\"\n (click)=\"prepareSuggestionPrompt(sug, $event)\"\n matTooltip=\"Refinar pedido\"\n aria-label=\"Refinar pedido\"\n >\n <mat-icon>edit</mat-icon>\n </button>\n <button\n mat-icon-button\n type=\"button\"\n class=\"suggestion-action-btn suggestion-action-btn--danger\"\n (click)=\"dismissSuggestion(sug, $event)\"\n matTooltip=\"Ocultar sugest\u00E3o\"\n aria-label=\"Ocultar sugest\u00E3o\"\n >\n <mat-icon>visibility_off</mat-icon>\n </button>\n </div>\n </div>\n }\n </div>\n } @else {\n <div class=\"suggestions-empty suggestions-empty--inline\">\n Todas as sugest\u00F5es foram ocultadas.\n </div>\n }\n </div>\n }\n @if (!loadingSuggestions && !richSuggestions.length) {\n <div class=\"suggestions-empty\">\n Nenhuma sugest\u00E3o dispon\u00EDvel no momento.\n </div>\n }\n @if (!loadingSuggestions && !richSuggestions.length) {\n <div class=\"suggestions-helper\">\n Selecione uma sugest\u00E3o acima ou descreva uma altera\u00E7\u00E3o no campo inferior.\n </div>\n }\n </div>\n }\n\n <!-- STATE: CLARIFICATION (Two-Step Flow) -->\n @if (state === 'clarification' && isActiveTab('task')) {\n <div\n class=\"clarification-area assistant-card\"\n id=\"assistant-panel-task\"\n role=\"tabpanel\"\n aria-labelledby=\"assistant-tab-task\"\n >\n @if (!shouldShowThoughtCard()) {\n <div class=\"task-header\">\n <div class=\"task-title\">{{ getTaskTitle() }}</div>\n <div class=\"task-subtitle\">{{ getTaskSubtitle() }}</div>\n @if (clarificationOptions.length > 1 && getTaskSelectionSummary(); as selectionSummary) {\n <div class=\"task-meta\">\n <span class=\"task-meta-label\">Selecionado:</span>\n <span class=\"task-meta-value\">{{ selectionSummary }}</span>\n </div>\n }\n @if (shouldShowTaskSteps()) {\n <div class=\"task-steps\">\n <span class=\"task-step active\">1 Dados</span>\n <span class=\"task-step\">2 Layout</span>\n <span class=\"task-step\">3 Revis\u00E3o</span>\n </div>\n }\n </div>\n }\n @if (clarificationResponseType === 'context') {\n <div class=\"context-only\">\n <mat-spinner diameter=\"24\"></mat-spinner>\n <div class=\"context-only-hint\">Buscando contexto adicional...</div>\n </div>\n }\n <ng-template #clarificationOptionContent let-opt let-index=\"index\" let-compact=\"compact\">\n @if (!compact) {\n <div class=\"clarification-decision-head\">\n <span class=\"clarification-decision-index\">{{ index + 1 }}</span>\n <span class=\"clarification-decision-type\">{{ getClarificationOptionKindLabel(opt) }}</span>\n <span class=\"spacer\"></span>\n @if (isClarificationSelected(opt)) {\n <span class=\"clarification-decision-state\">Selecionado</span>\n }\n </div>\n }\n @switch (getClarificationOptionLayout(opt)) {\n @case ('endpoint') {\n <div class=\"clarification-card\">\n <div class=\"clarification-card-header\">\n <mat-icon class=\"endpoint-icon\">{{ getEndpointIcon(opt) }}</mat-icon>\n @if (getEndpointMethod(opt); as method) {\n <span class=\"endpoint-method\" [attr.data-method]=\"method\">{{ method }}</span>\n }\n <span class=\"endpoint-label\">{{ opt.label }}</span>\n <span class=\"spacer\"></span>\n <mat-icon class=\"select-indicator\">\n {{ isClarificationSelected(opt) ? 'check_circle' : 'radio_button_unchecked' }}\n </mat-icon>\n </div>\n <div class=\"clarification-card-body\">\n @if (getEndpointPath(opt); as path) {\n <div class=\"endpoint-path\">{{ path }}</div>\n }\n @if (opt.contextHints?.description) {\n <div\n class=\"endpoint-description\"\n [matTooltip]=\"getDescriptionTooltip(opt)\"\n [matTooltipDisabled]=\"!shouldShowDescriptionTooltip(opt)\"\n >\n {{ opt.contextHints?.description }}\n </div>\n }\n </div>\n </div>\n }\n @case ('color') {\n <div class=\"clarification-color\">\n <span\n class=\"color-swatch\"\n [style.background]=\"getSafeHexColor(opt) || 'var(--md-sys-color-surface-container-highest)'\"\n ></span>\n <div class=\"color-meta\">\n <span class=\"color-label\">{{ opt.label }}</span>\n @if (opt.contextHints?.hexColor) {\n <span class=\"color-value\">{{ opt.contextHints?.hexColor }}</span>\n }\n </div>\n </div>\n }\n @case ('description') {\n <div class=\"clarification-description\">\n <span class=\"clarification-label\">{{ opt.label }}</span>\n @if (opt.contextHints?.description) {\n <span\n class=\"clarification-subtitle\"\n [matTooltip]=\"getDescriptionTooltip(opt)\"\n [matTooltipDisabled]=\"!shouldShowDescriptionTooltip(opt)\"\n >\n {{ opt.contextHints?.description }}\n </span>\n }\n </div>\n }\n @default {\n <span class=\"clarification-plain-label\">{{ opt.label }}</span>\n }\n }\n </ng-template>\n @if (warnings.length) {\n <div class=\"warnings-area\">\n <mat-icon class=\"warnings-icon\">warning_amber</mat-icon>\n <div class=\"warnings-content\">\n <div class=\"warnings-title\">Avisos</div>\n <div class=\"warnings-list\">\n @for (warning of warnings; track warning) {\n <div>{{ warning }}</div>\n }\n </div>\n </div>\n </div>\n }\n @if (clarificationQuestions.length) {\n <div\n class=\"clarification-questions\"\n [class.attention-highlight]=\"highlightClarificationDetails && !clarificationOptions.length\"\n >\n @for (question of clarificationQuestions; track question; let i = $index) {\n <div class=\"clarification-question\">\n <div class=\"clarification-question-label\">{{ question }}</div>\n <input\n type=\"text\"\n [(ngModel)]=\"clarificationAnswers[i]\"\n [placeholder]=\"'Resposta ' + (i + 1)\"\n autocomplete=\"off\">\n </div>\n }\n </div>\n }\n @if (clarificationOptions.length) {\n <div\n class=\"clarification-options-block\"\n [class.attention-highlight]=\"highlightClarificationDetails\"\n >\n <div class=\"clarification-options-title\">\n {{ clarificationOptions.length === 1 ? 'Decis\u00E3o sugerida' : 'Decis\u00F5es sugeridas' }}\n </div>\n @if (clarificationOptions.length === 1) {\n <div class=\"clarification-options-hint\">\n Etapa 2 de 4: confirme a melhor op\u00E7\u00E3o para continuar.\n </div>\n }\n @if (clarificationOptions.length > 1) {\n <div class=\"clarification-options-hint\">\n Etapa 2 de 4: selecione a alternativa mais aderente para gerar a proposta.\n </div>\n }\n @if (clarificationResponseType === 'confirm') {\n <div\n class=\"clarification-buttons\"\n [class.list]=\"clarificationPresentation === 'list'\"\n >\n @for (opt of clarificationOptions; track opt.value; let i = $index) {\n <button\n mat-button\n type=\"button\"\n (click)=\"onClarificationOptionClick(opt)\"\n class=\"clarification-option\"\n [class.selected]=\"isClarificationSelected(opt)\"\n [matTooltip]=\"getClarificationTooltip(opt)\"\n [matTooltipDisabled]=\"!shouldShowClarificationTooltip(opt) || isEndpointOption(opt)\"\n >\n <ng-container *ngTemplateOutlet=\"clarificationOptionContent; context: { $implicit: opt, index: i, compact: false }\"></ng-container>\n </button>\n }\n </div>\n }\n @if (clarificationSelectionMode === 'multiple') {\n <div\n class=\"clarification-buttons\"\n [class.list]=\"clarificationPresentation === 'list'\"\n >\n @for (opt of clarificationOptions; track opt.value; let i = $index) {\n <button\n mat-button\n type=\"button\"\n (click)=\"onClarificationOptionClick(opt)\"\n [class.selected]=\"isClarificationSelected(opt)\"\n class=\"clarification-option\"\n [matTooltip]=\"getClarificationTooltip(opt)\"\n [matTooltipDisabled]=\"!shouldShowClarificationTooltip(opt) || isEndpointOption(opt)\"\n >\n <ng-container *ngTemplateOutlet=\"clarificationOptionContent; context: { $implicit: opt, index: i, compact: false }\"></ng-container>\n </button>\n }\n </div>\n }\n @if (clarificationResponseType !== 'confirm' && clarificationSelectionMode === 'single' && clarificationPresentation !== 'chips') {\n <div\n class=\"clarification-buttons\"\n [class.list]=\"clarificationPresentation === 'list'\"\n >\n @for (opt of clarificationOptions; track opt.value; let i = $index) {\n <button\n mat-button\n type=\"button\"\n (click)=\"onClarificationOptionClick(opt)\"\n class=\"clarification-option\"\n [class.selected]=\"isClarificationSelected(opt)\"\n [matTooltip]=\"getClarificationTooltip(opt)\"\n [matTooltipDisabled]=\"!shouldShowClarificationTooltip(opt) || isEndpointOption(opt)\"\n >\n <ng-container *ngTemplateOutlet=\"clarificationOptionContent; context: { $implicit: opt, index: i, compact: false }\"></ng-container>\n </button>\n }\n </div>\n }\n @if (clarificationResponseType !== 'confirm' && clarificationSelectionMode === 'single' && clarificationPresentation === 'chips') {\n <div\n class=\"clarification-chips\"\n >\n @for (opt of clarificationOptions; track opt.value; let i = $index) {\n @if (isEndpointOption(opt)) {\n <button\n mat-button\n type=\"button\"\n class=\"clarification-option clarification-card-button\"\n (click)=\"onClarificationOptionClick(opt)\"\n [class.selected]=\"isClarificationSelected(opt)\"\n [matTooltip]=\"getClarificationTooltip(opt)\"\n [matTooltipDisabled]=\"!shouldShowClarificationTooltip(opt) || isEndpointOption(opt)\"\n >\n <ng-container *ngTemplateOutlet=\"clarificationOptionContent; context: { $implicit: opt, index: i, compact: false }\"></ng-container>\n </button>\n } @else {\n <mat-chip\n (click)=\"onClarificationOptionClick(opt)\"\n [matTooltip]=\"getClarificationTooltip(opt)\"\n [matTooltipDisabled]=\"!shouldShowClarificationTooltip(opt)\"\n class=\"clarification-chip\"\n >\n <ng-container *ngTemplateOutlet=\"clarificationOptionContent; context: { $implicit: opt, index: i, compact: true }\"></ng-container>\n </mat-chip>\n }\n }\n </div>\n }\n </div>\n }\n @if (clarificationAllowCustom && clarificationResponseType !== 'context') {\n <div\n class=\"clarification-manual-toggle\"\n >\n <span class=\"clarification-manual-label\">N\u00E3o encontrou o recurso?</span>\n <button mat-button type=\"button\" (click)=\"toggleManualInput()\">\n {{ showManualInput ? 'Ocultar resposta manual' : 'Responder manualmente' }}\n </button>\n </div>\n }\n @if (clarificationAllowCustom && showManualInput && clarificationResponseType !== 'context') {\n <div\n class=\"clarification-free\"\n >\n <input\n type=\"text\"\n [(ngModel)]=\"clarificationFreeText\"\n placeholder=\"Digite sua resposta\u2026\"\n autocomplete=\"off\"\n (keydown.enter)=\"confirmTaskAction()\"\n />\n </div>\n }\n @if (clarificationAllowCustom && showManualInput && clarificationResponseType !== 'context') {\n <div\n class=\"clarification-free-hint\"\n >\n Pressione Enter para enviar.\n </div>\n }\n </div>\n }\n\n <!-- STATE: REVIEW (Diff/Explanation) -->\n @if (state === 'review' && isActiveTab('task')) {\n <div\n class=\"review-area assistant-card\"\n id=\"assistant-panel-task\"\n role=\"tabpanel\"\n aria-labelledby=\"assistant-tab-task\"\n >\n @if (!shouldShowThoughtCard()) {\n <div class=\"task-header\">\n <div class=\"task-title\">{{ getTaskTitle() }}</div>\n <div class=\"task-subtitle\">{{ getTaskSubtitle() }}</div>\n @if (clarificationOptions.length > 1 && getTaskSelectionSummary(); as selectionSummary) {\n <div class=\"task-meta\">\n <span class=\"task-meta-label\">Selecionado:</span>\n <span class=\"task-meta-value\">{{ selectionSummary }}</span>\n </div>\n }\n @if (shouldShowTaskSteps()) {\n <div class=\"task-steps\">\n <span class=\"task-step\">1 Dados</span>\n <span class=\"task-step\">2 Layout</span>\n <span class=\"task-step active\">3 Revis\u00E3o</span>\n </div>\n }\n </div>\n }\n @if (warnings.length) {\n <div class=\"warnings-area\">\n <mat-icon class=\"warnings-icon\">warning_amber</mat-icon>\n <div class=\"warnings-content\">\n <div class=\"warnings-title\">Avisos</div>\n <div class=\"warnings-list\">\n @for (warning of warnings; track warning) {\n <div>{{ warning }}</div>\n }\n </div>\n </div>\n </div>\n }\n <div class=\"review-trust\">\n <span class=\"trust-chip\" [matTooltip]=\"getScopeTooltip()\">{{ getScopeLabel() }}</span>\n <span class=\"trust-chip\" [matTooltip]=\"getConfidenceTooltip()\">{{ getConfidenceLabel() }}</span>\n <span class=\"trust-chip risk-chip\" [class.medium]=\"getReviewRiskLevel() === 'm\u00E9dio'\" [class.high]=\"getReviewRiskLevel() === 'alto'\">\n Risco {{ getReviewRiskLevel() }}\n </span>\n </div>\n <div class=\"review-summary\" [class.attention-highlight]=\"highlightReviewDetails\">\n <div class=\"review-summary-title\">Resumo da proposta</div>\n <div class=\"review-summary-line\">{{ getReviewSummary() }}</div>\n </div>\n <div class=\"review-diff\">\n <div class=\"review-diff-title\">Pr\u00E9via de mudan\u00E7as</div>\n @if (pendingDiff.length) {\n <div class=\"review-diff-summary\">\n @for (line of getDiffSummaryLines(); track line) {\n <div class=\"review-diff-line\">{{ line }}</div>\n }\n @if (pendingDiff.length > 3) {\n <div class=\"review-diff-more\">\u2026 +{{ pendingDiff.length - 3 }} mudan\u00E7as</div>\n }\n </div>\n <button mat-stroked-button type=\"button\" class=\"review-diff-toggle\" (click)=\"toggleFullDiff()\">\n {{ getDiffToggleLabel() }}\n </button>\n } @else {\n <div class=\"review-diff-empty\">\n N\u00E3o foi poss\u00EDvel gerar um diff estruturado. Revise o resumo e aplique com cautela.\n </div>\n }\n @if (showFullDiff && pendingDiff.length) {\n <div class=\"review-diff-full\">\n @for (diff of pendingDiff; track diff.path) {\n <div class=\"review-diff-block\">\n <div class=\"review-diff-path\">{{ diff.path }}</div>\n <div class=\"review-diff-label\">Antes:</div>\n <pre>{{ diff.before | json }}</pre>\n <div class=\"review-diff-label\">Depois:</div>\n <pre>{{ diff.after | json }}</pre>\n </div>\n }\n </div>\n }\n </div>\n @if (aiExplanation.trim()) {\n <div class=\"ai-explanation\">\n {{ aiExplanation }}\n </div>\n }\n </div>\n }\n\n <!-- STATE: ERROR -->\n @if (state === 'error' && (isActiveTab('task') || (!isTaskMode() && isActiveTab('suggestions')))) {\n <div\n class=\"error-area assistant-card\"\n [attr.id]=\"isTaskMode() ? 'assistant-panel-task' : 'assistant-panel-suggestions'\"\n role=\"tabpanel\"\n [attr.aria-labelledby]=\"isTaskMode() ? 'assistant-tab-task' : 'assistant-tab-suggestions'\"\n >\n <div class=\"error-msg\">\n <mat-icon color=\"warn\">error_outline</mat-icon>\n <span>{{ errorMsg }}</span>\n </div>\n @if (warnings.length) {\n <div class=\"warnings-area\">\n <mat-icon class=\"warnings-icon\">warning_amber</mat-icon>\n <div class=\"warnings-content\">\n <div class=\"warnings-title\">Avisos</div>\n <div class=\"warnings-list\">\n @for (warning of warnings; track warning) {\n <div>{{ warning }}</div>\n }\n </div>\n </div>\n </div>\n }\n @if (shouldShowApplyDetails()) {\n <div class=\"apply-details\">\n <div class=\"apply-details-header\">\n <div class=\"apply-details-title\">Detalhes da aplica\u00E7\u00E3o</div>\n @if (allowManualPatchEdit) {\n <div class=\"apply-details-actions\">\n <button mat-button type=\"button\" (click)=\"togglePatchPathEditor()\" [disabled]=\"!pendingPatch\">\n {{ patchPathEditorExpanded ? 'Ocultar paths' : 'Editar por path' }}\n </button>\n <button mat-button type=\"button\" (click)=\"togglePatchEditor()\" [disabled]=\"!pendingPatch\">\n {{ patchEditorExpanded ? 'Ocultar editor' : 'Editar patch' }}\n </button>\n </div>\n }\n </div>\n @if (lastApplyAt) {\n <div class=\"apply-details-meta\">\n \u00DAltima tentativa: {{ lastApplyAt | date:'short' }}\n </div>\n }\n @if (getApplyPaths().length) {\n <div class=\"apply-paths\">\n @for (path of getApplyPaths(); track path) {\n <span class=\"apply-path-chip\">{{ path }}</span>\n }\n </div>\n }\n @if (applyWarnings.length) {\n <div class=\"apply-warnings\">\n <div class=\"apply-warnings-title\">Avisos da aplica\u00E7\u00E3o</div>\n <div class=\"apply-warnings-list\">\n @for (warning of applyWarnings; track warning) {\n <div>{{ warning }}</div>\n }\n </div>\n </div>\n }\n @if (allowManualPatchEdit && patchPathEditorExpanded) {\n <div class=\"patch-path-editor\">\n <div class=\"patch-editor-label\">Editar por path</div>\n <div class=\"patch-editor-hint\">Texto simples vira string; para for\u00E7ar texto em true/false/n\u00FAmero, use aspas.</div>\n @if (!getEditablePatchPathEdits().length) {\n <div class=\"patch-path-editor-empty\">\n Nenhum path edit\u00E1vel dispon\u00EDvel para este patch.\n </div>\n }\n @if (getEditablePatchPathEdits().length) {\n <div class=\"patch-path-rows\">\n @for (edit of getEditablePatchPathEdits(); track edit.path; let i = $index) {\n <div class=\"patch-path-row\">\n <div class=\"patch-path-label\">{{ edit.path }}</div>\n <input\n type=\"text\"\n [(ngModel)]=\"patchPathEdits[i].valueText\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n />\n @if (patchPathEdits[i].error) {\n <div class=\"patch-editor-error\">{{ patchPathEdits[i].error }}</div>\n }\n </div>\n }\n </div>\n }\n @if (patchPathEditorError) {\n <div class=\"patch-editor-error\">{{ patchPathEditorError }}</div>\n }\n <div class=\"patch-editor-actions\">\n <button mat-button type=\"button\" (click)=\"resetPatchPathEdits()\">\n Restaurar valores\n </button>\n <button mat-button type=\"button\" (click)=\"applyPathEditsToPatch()\">\n Aplicar no patch\n </button>\n <button mat-flat-button color=\"primary\" type=\"button\" (click)=\"reapplyPathEdits()\">\n Reaplicar por path\n </button>\n </div>\n </div>\n }\n @if (allowManualPatchEdit && patchEditorExpanded) {\n <div class=\"patch-editor\">\n <label class=\"patch-editor-label\">Patch JSON</label>\n <textarea\n [(ngModel)]=\"patchEditorText\"\n spellcheck=\"false\"\n ></textarea>\n @if (patchEditorError) {\n <div class=\"patch-editor-error\">{{ patchEditorError }}</div>\n }\n <div class=\"patch-editor-actions\">\n <button mat-button type=\"button\" (click)=\"resetPatchEditor()\">\n Restaurar original\n </button>\n <button mat-flat-button color=\"primary\" type=\"button\" (click)=\"reapplyEditedPatch()\">\n Reaplicar patch\n </button>\n </div>\n </div>\n }\n </div>\n }\n <div class=\"review-actions\">\n <button mat-button (click)=\"close()\">Fechar</button>\n <button mat-stroked-button (click)=\"retry()\">Tentar Novamente</button>\n </div>\n </div>\n }\n\n <!-- STATE: SUCCESS -->\n @if (state === 'success' && (isActiveTab('task') || (!isTaskMode() && isActiveTab('suggestions')))) {\n <div\n class=\"success-area assistant-card\"\n [attr.id]=\"isTaskMode() ? 'assistant-panel-task' : 'assistant-panel-suggestions'\"\n role=\"tabpanel\"\n [attr.aria-labelledby]=\"isTaskMode() ? 'assistant-tab-task' : 'assistant-tab-suggestions'\"\n >\n <div class=\"success-msg\">\n <mat-icon class=\"success-icon\">check_circle</mat-icon>\n <span>{{ aiExplanation || 'Configura\u00E7\u00E3o atualizada.' }}</span>\n </div>\n @if (warnings.length) {\n <div class=\"warnings-area\">\n <mat-icon class=\"warnings-icon\">warning_amber</mat-icon>\n <div class=\"warnings-content\">\n <div class=\"warnings-title\">Avisos</div>\n <div class=\"warnings-list\">\n @for (warning of warnings; track warning) {\n <div>{{ warning }}</div>\n }\n </div>\n </div>\n </div>\n }\n @if (shouldShowApplyDetails()) {\n <div class=\"apply-details\">\n <div class=\"apply-details-header\">\n <div class=\"apply-details-title\">Detalhes da aplica\u00E7\u00E3o</div>\n @if (allowManualPatchEdit) {\n <div class=\"apply-details-actions\">\n <button mat-button type=\"button\" (click)=\"togglePatchPathEditor()\" [disabled]=\"!pendingPatch\">\n {{ patchPathEditorExpanded ? 'Ocultar paths' : 'Editar por path' }}\n </button>\n <button mat-button type=\"button\" (click)=\"togglePatchEditor()\" [disabled]=\"!pendingPatch\">\n {{ patchEditorExpanded ? 'Ocultar editor' : 'Editar e reaplicar' }}\n </button>\n </div>\n }\n </div>\n @if (lastApplyAt) {\n <div class=\"apply-details-meta\">\n Aplicado em {{ lastApplyAt | date:'short' }}\n </div>\n }\n @if (getApplyPaths().length) {\n <div class=\"apply-paths\">\n @for (path of getApplyPaths(); track path) {\n <span class=\"apply-path-chip\">{{ path }}</span>\n }\n </div>\n }\n @if (applyWarnings.length) {\n <div class=\"apply-warnings\">\n <div class=\"apply-warnings-title\">Avisos da aplica\u00E7\u00E3o</div>\n <div class=\"apply-warnings-list\">\n @for (warning of applyWarnings; track warning) {\n <div>{{ warning }}</div>\n }\n </div>\n </div>\n }\n @if (allowManualPatchEdit && patchPathEditorExpanded) {\n <div class=\"patch-path-editor\">\n <div class=\"patch-editor-label\">Editar por path</div>\n <div class=\"patch-editor-hint\">Texto simples vira string; para for\u00E7ar texto em true/false/n\u00FAmero, use aspas.</div>\n @if (!getEditablePatchPathEdits().length) {\n <div class=\"patch-path-editor-empty\">\n Nenhum path edit\u00E1vel dispon\u00EDvel para este patch.\n </div>\n }\n @if (getEditablePatchPathEdits().length) {\n <div class=\"patch-path-rows\">\n @for (edit of getEditablePatchPathEdits(); track edit.path; let i = $index) {\n <div class=\"patch-path-row\">\n <div class=\"patch-path-label\">{{ edit.path }}</div>\n <input\n type=\"text\"\n [(ngModel)]=\"patchPathEdits[i].valueText\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n />\n @if (patchPathEdits[i].error) {\n <div class=\"patch-editor-error\">{{ patchPathEdits[i].error }}</div>\n }\n </div>\n }\n </div>\n }\n @if (patchPathEditorError) {\n <div class=\"patch-editor-error\">{{ patchPathEditorError }}</div>\n }\n <div class=\"patch-editor-actions\">\n <button mat-button type=\"button\" (click)=\"resetPatchPathEdits()\">\n Restaurar valores\n </button>\n <button mat-button type=\"button\" (click)=\"applyPathEditsToPatch()\">\n Aplicar no patch\n </button>\n <button mat-flat-button color=\"primary\" type=\"button\" (click)=\"reapplyPathEdits()\">\n Reaplicar por path\n </button>\n </div>\n </div>\n }\n @if (allowManualPatchEdit && patchEditorExpanded) {\n <div class=\"patch-editor\">\n <label class=\"patch-editor-label\">Patch JSON</label>\n <textarea\n [(ngModel)]=\"patchEditorText\"\n spellcheck=\"false\"\n ></textarea>\n @if (patchEditorError) {\n <div class=\"patch-editor-error\">{{ patchEditorError }}</div>\n }\n <div class=\"patch-editor-actions\">\n <button mat-button type=\"button\" (click)=\"resetPatchEditor()\">\n Restaurar original\n </button>\n <button mat-flat-button color=\"primary\" type=\"button\" (click)=\"reapplyEditedPatch()\">\n Reaplicar patch\n </button>\n </div>\n </div>\n }\n </div>\n }\n <button mat-button color=\"warn\" (click)=\"undoLastChange()\">\n <mat-icon>undo</mat-icon> Desfazer\n </button>\n </div>\n }\n\n </div>\n\n <div class=\"assistant-footer\">\n @if (!isTaskMode()) {\n <button\n mat-icon-button\n type=\"button\"\n class=\"composer-leading composer-leading-btn\"\n [matMenuTriggerFor]=\"assistantQuickMenu\"\n aria-label=\"Abrir a\u00E7\u00F5es r\u00E1pidas\"\n matTooltip=\"A\u00E7\u00F5es r\u00E1pidas\"\n >\n <mat-icon>add</mat-icon>\n </button>\n <input\n #inputEl\n type=\"text\"\n [(ngModel)]=\"userPrompt\"\n [disabled]=\"state === 'processing' || state === 'applying'\"\n placeholder=\"Descreva a altera\u00E7\u00E3o que deseja aplicar\u2026\"\n autocomplete=\"off\"\n />\n <div class=\"send-actions\">\n @if (state === 'listening') {\n <button\n mat-icon-button\n class=\"send-btn\"\n (click)=\"submitPrompt()\"\n [disabled]=\"!userPrompt.trim()\"\n [class.ready]=\"!!userPrompt.trim()\"\n >\n <mat-icon>arrow_upward</mat-icon>\n </button>\n }\n @if (state === 'processing' || state === 'applying') {\n <mat-spinner diameter=\"20\"></mat-spinner>\n }\n </div>\n } @else {\n <div class=\"task-footer\">\n <div class=\"task-footer-left\">\n <button mat-button type=\"button\" (click)=\"handleTaskSecondary()\">{{ getTaskCancelLabel() }}</button>\n @if (state === 'review') {\n <button\n mat-stroked-button\n type=\"button\"\n (click)=\"retry()\"\n >\n {{ getTaskSecondaryLabel() }}\n </button>\n }\n </div>\n <div class=\"task-footer-right\">\n <button\n class=\"task-primary-btn\"\n mat-flat-button\n color=\"primary\"\n type=\"button\"\n (click)=\"confirmTaskAction()\"\n [disabled]=\"isTaskPrimaryDisabled()\"\n >\n {{ getTaskPrimaryLabel() }}\n </button>\n @if (state === 'processing' || state === 'applying') {\n <mat-spinner diameter=\"20\"></mat-spinner>\n }\n </div>\n </div>\n }\n </div>\n\n <mat-menu #assistantQuickMenu=\"matMenu\" panelClass=\"assistant-quick-menu-panel\">\n <button mat-menu-item type=\"button\" (click)=\"setActiveTab('chat')\">\n <mat-icon>history</mat-icon>\n <span>Hist\u00F3rico</span>\n </button>\n <button mat-menu-item type=\"button\" (click)=\"setActiveTab('suggestions')\">\n <mat-icon>lightbulb</mat-icon>\n <span>Sugest\u00F5es</span>\n </button>\n <button mat-menu-item type=\"button\" (click)=\"startNewSession()\">\n <mat-icon>add_comment</mat-icon>\n <span>Nova conversa</span>\n </button>\n <button mat-menu-item type=\"button\" (click)=\"refreshSuggestions()\" [disabled]=\"loadingSuggestions\">\n <mat-icon>refresh</mat-icon>\n <span>Atualizar sugest\u00F5es</span>\n </button>\n <button\n mat-menu-item\n type=\"button\"\n (click)=\"restoreDismissedSuggestions()\"\n [disabled]=\"!hasDismissedSuggestions()\"\n >\n <mat-icon>visibility</mat-icon>\n <span>Restaurar sugest\u00F5es ocultas</span>\n </button>\n <button\n mat-menu-item\n type=\"button\"\n class=\"assistant-quick-menu-danger\"\n (click)=\"clearHistory()\"\n [disabled]=\"!historySessions.length\"\n >\n <mat-icon>delete_outline</mat-icon>\n <span>Limpar hist\u00F3rico local</span>\n </button>\n </mat-menu>\n </div>\n\n</ng-template>\n", styles: ["@keyframes assistantPremiumEnter{0%{opacity:0;transform:translate(14px) scale(.99)}to{opacity:1;transform:translate(0) scale(1)}}:host ::ng-deep .ai-assistant-backdrop{background:color-mix(in srgb,var(--md-sys-color-scrim, var(--md-sys-color-shadow, var(--md-sys-color-on-surface))) 42%,transparent);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}::ng-deep .ai-assistant-overlay-pane{max-width:calc(100vw - 24px);max-height:calc(100vh - 24px)}.ai-assistant-panel{box-sizing:border-box;width:min(604px,100vw - 18px);min-height:min(620px,100vh - 18px);max-height:min(820px,100vh - 18px);display:flex;flex-direction:column;overflow:hidden;color:var(--md-sys-color-on-surface);border-left:1px solid color-mix(in srgb,var(--md-sys-color-primary) 24%,var(--md-sys-color-outline-variant));border-top:1px solid color-mix(in srgb,var(--md-sys-color-primary) 18%,var(--md-sys-color-outline-variant));border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-primary) 18%,var(--md-sys-color-outline-variant));box-shadow:0 18px 48px color-mix(in srgb,var(--md-sys-color-shadow, var(--md-sys-color-on-surface)) 42%,transparent),inset 0 1px color-mix(in srgb,var(--md-sys-color-on-surface) 10%,transparent);background:radial-gradient(circle at 14% 8%,color-mix(in srgb,var(--md-sys-color-primary-container) 38%,transparent) 0%,transparent 44%),linear-gradient(165deg,color-mix(in srgb,var(--md-sys-color-surface-container-highest) 88%,var(--md-sys-color-surface)),var(--md-sys-color-surface));animation:assistantPremiumEnter .24s cubic-bezier(.22,1,.36,1)}.assistant-header{position:relative;display:flex;align-items:flex-start;justify-content:space-between;gap:12px;padding:12px 16px 10px;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-primary) 18%,var(--md-sys-color-outline-variant));background:linear-gradient(130deg,color-mix(in srgb,var(--md-sys-color-primary-container) 28%,transparent) 0%,transparent 52%),var(--md-sys-color-surface-container-low)}.assistant-header:after{content:\"\";position:absolute;left:16px;right:16px;bottom:-1px;height:1px;background:linear-gradient(90deg,color-mix(in srgb,var(--md-sys-color-primary) 55%,transparent),transparent);pointer-events:none}.assistant-header .assistant-header__left{min-width:0;display:flex;align-items:flex-start;gap:12px}.assistant-header .magic-icon{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;width:30px;height:30px;font-size:18px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 30%,transparent);box-shadow:0 4px 12px color-mix(in srgb,var(--md-sys-color-primary) 26%,transparent)}.assistant-header .assistant-title-group{min-width:0;display:flex;flex-direction:column;gap:4px}.assistant-header .assistant-title{font-size:15px;font-weight:700;letter-spacing:.01em;overflow-wrap:anywhere}.assistant-header .assistant-subtitle{display:block;font-size:11px;line-height:1.25;color:color-mix(in srgb,var(--md-sys-color-on-surface) 70%,var(--md-sys-color-on-surface-variant));overflow-wrap:anywhere}.assistant-header-chips{display:inline-flex;align-items:center;flex-wrap:wrap;gap:6px}.assistant-header .mode-chip{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:999px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 28%,var(--md-sys-color-outline-variant));background:color-mix(in srgb,var(--md-sys-color-primary-container) 64%,var(--md-sys-color-surface-container));color:color-mix(in srgb,var(--md-sys-color-on-primary-container) 85%,var(--md-sys-color-on-surface));font-size:10px;font-weight:700;letter-spacing:.04em;text-transform:uppercase}.assistant-header .mode-chip:before{content:\"\";width:6px;height:6px;border-radius:999px;background:currentColor;box-shadow:0 0 0 3px color-mix(in srgb,currentColor 16%,transparent)}.assistant-header .mode-chip.mock{border-color:color-mix(in srgb,var(--md-sys-color-error) 34%,var(--md-sys-color-outline-variant));background:color-mix(in srgb,var(--md-sys-color-error-container) 72%,var(--md-sys-color-surface-container));color:color-mix(in srgb,var(--md-sys-color-on-error-container) 85%,var(--md-sys-color-error))}.assistant-header .policy-chip{padding:2px 8px;border-radius:999px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 84%,transparent);background:var(--md-sys-color-surface-container-high);font-size:10px;letter-spacing:.02em;font-weight:600}.assistant-header .policy-chip.strict{border-color:color-mix(in srgb,var(--md-sys-color-primary) 42%,var(--md-sys-color-outline-variant));background:color-mix(in srgb,var(--md-sys-color-primary-container) 56%,var(--md-sys-color-surface-container-high))}.assistant-status{display:flex;align-items:flex-start;gap:10px;padding:10px 16px;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-primary) 18%,var(--md-sys-color-outline-variant));border-radius:0;background:linear-gradient(160deg,color-mix(in srgb,var(--md-sys-color-primary-container) 24%,transparent),transparent 48%),var(--md-sys-color-surface-container-low)}.assistant-status-dot{width:8px;height:8px;margin-top:6px;border-radius:999px;flex:0 0 auto;background:var(--md-sys-color-primary);box-shadow:0 0 0 4px color-mix(in srgb,var(--md-sys-color-primary) 16%,transparent)}.assistant-status.warning .assistant-status-dot{background:var(--md-sys-color-error);box-shadow:0 0 0 4px color-mix(in srgb,var(--md-sys-color-error) 16%,transparent)}.assistant-status.success .assistant-status-dot{background:color-mix(in srgb,var(--md-sys-color-primary) 74%,var(--md-sys-color-tertiary, var(--md-sys-color-primary)))}.assistant-status-content{min-width:0;display:flex;flex-direction:column;gap:2px}.assistant-status-label{display:flex;align-items:center;flex-wrap:wrap;gap:4px;font-size:12px;font-weight:700;line-height:1.35}.assistant-status-detail{font-size:11px;line-height:1.4;color:var(--md-sys-color-on-surface-variant);overflow-wrap:anywhere}.assistant-status-mode{padding:1px 6px;border-radius:999px;background:color-mix(in srgb,var(--md-sys-color-primary-container) 72%,transparent);color:var(--md-sys-color-on-primary-container);font-size:10px;font-weight:700}.assistant-nav{padding:8px 16px 0}.assistant-nav .assistant-tabs{display:flex;align-items:center;gap:4px;border-radius:12px;padding:5px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 24%,var(--md-sys-color-outline-variant));border-color:color-mix(in srgb,var(--md-sys-color-primary) 24%,var(--md-sys-color-outline-variant));background:linear-gradient(155deg,color-mix(in srgb,var(--md-sys-color-primary-container) 14%,transparent),transparent 58%),var(--md-sys-color-surface-container-low)}.assistant-nav .assistant-tab{appearance:none;min-width:0;min-height:30px;border:0;border-radius:8px;padding:0 10px;background:transparent;color:var(--md-sys-color-on-surface-variant);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;flex:1 1 0;font-size:11px;font-weight:700;letter-spacing:.01em}.assistant-nav .assistant-tab.active{background:var(--md-sys-color-surface-container-highest);color:var(--md-sys-color-on-surface);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--md-sys-color-primary) 34%,transparent),0 6px 12px color-mix(in srgb,var(--md-sys-color-primary) 18%,transparent)}.assistant-section,.assistant-card{border-radius:14px;border-color:color-mix(in srgb,var(--md-sys-color-primary) 20%,var(--md-sys-color-outline-variant));background:linear-gradient(160deg,color-mix(in srgb,var(--md-sys-color-primary-container) 16%,transparent),transparent 50%),var(--md-sys-color-surface-container-lowest);box-shadow:0 6px 18px color-mix(in srgb,var(--md-sys-color-shadow, var(--md-sys-color-on-surface)) 12%,transparent),inset 0 1px color-mix(in srgb,var(--md-sys-color-on-surface) 7%,transparent)}.suggestions-hero{margin:2px 0 4px;padding:10px 12px;border-radius:12px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 24%,var(--md-sys-color-outline-variant));background:linear-gradient(120deg,color-mix(in srgb,var(--md-sys-color-primary-container) 34%,transparent) 0%,transparent 52%),var(--md-sys-color-surface-container-low)}.suggestions-hero__label{font-size:10px;letter-spacing:.08em;text-transform:uppercase;font-weight:700;color:var(--md-sys-color-on-surface-variant);opacity:.88}.suggestions-hero__title{margin-top:2px;font-size:13px;font-weight:700;color:var(--md-sys-color-on-surface)}.suggestions-hero__detail{margin-top:4px;font-size:12px;line-height:1.4;color:color-mix(in srgb,var(--md-sys-color-on-surface) 78%,var(--md-sys-color-on-surface-variant))}.suggestions-content .suggestion-item{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:12px;padding:12px;border-radius:12px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 18%,var(--md-sys-color-outline-variant));border-color:color-mix(in srgb,var(--md-sys-color-primary) 18%,var(--md-sys-color-outline-variant));background:linear-gradient(140deg,color-mix(in srgb,var(--md-sys-color-primary-container) 16%,transparent),transparent 56%),var(--md-sys-color-surface-container-lowest);transition:transform .2s cubic-bezier(.25,.8,.25,1),border-color .2s ease,box-shadow .2s ease}.suggestions-list{display:flex;flex-direction:column;gap:10px}.suggestion-copy{min-width:0;display:grid;gap:4px}.suggestion-main{min-width:0;display:flex;align-items:center;flex-wrap:wrap;gap:8px}.suggestion-icon{width:18px;height:18px;font-size:18px;flex:0 0 auto;color:var(--md-sys-color-primary)}.suggestion-label{min-width:0;font-size:13px;font-weight:700;line-height:1.35;overflow-wrap:anywhere}.suggestion-group{padding:2px 6px;border-radius:999px;background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface-variant);font-size:10px;font-weight:700;line-height:1.2}.suggestion-desc{font-size:12px;line-height:1.35;color:var(--md-sys-color-on-surface-variant);overflow-wrap:anywhere}.suggestion-actions{display:inline-flex;align-items:center;justify-content:flex-end;gap:4px}.suggestion-action-btn,.suggestion-arrow{width:32px;height:32px;display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;color:var(--md-sys-color-on-surface-variant)}.suggestions-content .suggestion-item:hover,.suggestions-content .suggestion-item:focus-visible{border-color:color-mix(in srgb,var(--md-sys-color-primary) 58%,var(--md-sys-color-outline-variant));box-shadow:0 8px 18px color-mix(in srgb,var(--md-sys-color-primary) 18%,transparent),inset 0 0 0 1px color-mix(in srgb,var(--md-sys-color-primary) 28%,transparent);transform:translateY(-2px) scale(1.01)}.assistant-footer{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:8px;padding:10px 16px;border-top-color:color-mix(in srgb,var(--md-sys-color-primary) 20%,var(--md-sys-color-outline-variant));background:linear-gradient(180deg,color-mix(in srgb,var(--md-sys-color-primary-container) 16%,transparent),transparent 56%),var(--md-sys-color-surface-container-low)}.assistant-footer .task-footer{grid-column:1/-1}.composer-leading{width:30px;height:30px;display:inline-flex;align-items:center;justify-content:center;border-radius:999px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 30%,var(--md-sys-color-outline-variant));background:color-mix(in srgb,var(--md-sys-color-primary-container) 70%,var(--md-sys-color-surface-container-low));color:var(--md-sys-color-primary);box-shadow:0 4px 10px color-mix(in srgb,var(--md-sys-color-primary) 16%,transparent)}.composer-leading mat-icon{width:16px;height:16px;font-size:16px}.assistant-footer input{box-sizing:border-box;width:100%;min-width:0;height:34px;border:1px solid;border-radius:8px;padding:0 12px;color:var(--md-sys-color-on-surface);border-color:color-mix(in srgb,var(--md-sys-color-primary) 24%,var(--md-sys-color-outline-variant));background:var(--md-sys-color-surface);box-shadow:inset 0 1px 2px color-mix(in srgb,var(--md-sys-color-shadow, var(--md-sys-color-on-surface)) 12%,transparent)}.send-actions{min-width:36px;display:inline-flex;align-items:center;justify-content:center}.assistant-footer .send-btn{--mdc-icon-button-icon-size: 20px;--mdc-icon-button-state-layer-size: 36px;--mat-icon-button-state-layer-size: 36px;width:36px;height:36px;padding:8px;line-height:1;display:inline-flex;align-items:center;justify-content:center;border-color:color-mix(in srgb,var(--md-sys-color-primary) 24%,var(--md-sys-color-outline-variant));background:var(--md-sys-color-surface)}.assistant-footer .send-btn mat-icon{width:20px;height:20px;margin:0;font-size:20px;line-height:20px;display:inline-flex;align-items:center;justify-content:center}.assistant-footer .send-btn.ready{background:linear-gradient(135deg,color-mix(in srgb,var(--md-sys-color-primary-container) 84%,var(--md-sys-color-primary)),var(--md-sys-color-primary));color:var(--md-sys-color-on-primary);box-shadow:0 8px 18px color-mix(in srgb,var(--md-sys-color-primary) 30%,transparent)}.task-primary-btn{border-radius:12px;box-shadow:0 8px 18px color-mix(in srgb,var(--md-sys-color-primary) 24%,transparent)}@media(max-width:959px){.assistant-header{padding:12px 12px 10px}.assistant-section,.assistant-card{margin:4px 12px 10px}.assistant-header:after{left:12px;right:12px}.assistant-header .assistant-title{font-size:14px}.assistant-header .assistant-subtitle{font-size:10px}.assistant-footer{grid-template-columns:minmax(0,1fr) auto}.composer-leading{display:none}}.assistant-thought{margin-top:0;gap:10px;border-color:color-mix(in srgb,var(--md-sys-color-primary) 26%,var(--md-sys-color-outline-variant));background:linear-gradient(145deg,color-mix(in srgb,var(--md-sys-color-primary-container) 28%,transparent),transparent 58%),var(--md-sys-color-surface-container-low)}.assistant-thought-meta{display:inline-flex;align-items:center;gap:6px;font-size:11px;color:var(--md-sys-color-on-surface-variant)}.assistant-thought-meta mat-icon{width:15px;height:15px;font-size:15px;color:var(--md-sys-color-primary)}.assistant-thought-summary{font-size:13px;line-height:1.45;color:var(--md-sys-color-on-surface)}.assistant-thought-plan{border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 32%,var(--md-sys-color-outline-variant));border-radius:12px;padding:10px;background:var(--md-sys-color-surface-container-lowest);display:flex;flex-direction:column;gap:8px}.assistant-thought-plan-title{font-size:13px;font-weight:700;color:var(--md-sys-color-on-surface)}.assistant-thought-plan-actions{display:grid;grid-template-columns:repeat(auto-fit,minmax(0,1fr));gap:8px}.assistant-thought-plan-actions .mdc-button{min-width:0}.assistant-thought-plan-hint{font-size:11px;color:var(--md-sys-color-on-surface-variant);line-height:1.35}.assistant-thought-checklist{display:flex;flex-direction:column;gap:5px}.assistant-thought-checklist-item{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--md-sys-color-on-surface-variant)}.assistant-thought-checklist-item mat-icon{width:14px;height:14px;font-size:14px}.assistant-thought-shimmer{display:flex;flex-direction:column;gap:8px;margin-top:4px}.assistant-thought-shimmer .shimmer-line{height:12px;border-radius:4px;position:relative;overflow:hidden;background:var(--md-sys-color-surface-container-highest)}.assistant-thought-shimmer .shimmer-line:after{content:\"\";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--md-sys-color-primary) 8%,transparent),transparent);animation:assistantShimmerEffect 1.5s infinite}.assistant-thought-shimmer .shimmer-line-1{width:85%}.assistant-thought-shimmer .shimmer-line-2{width:92%}.assistant-thought-shimmer .shimmer-line-3{width:64%}@keyframes assistantShimmerEffect{to{transform:translate(100%)}}.assistant-flow{grid-template-columns:1fr;gap:6px}.flow-step{display:flex;align-items:flex-start;gap:8px;text-align:left;padding:7px 8px;border-radius:10px}.flow-step-index{width:18px;height:18px;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;font-size:10px;font-weight:700;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-highest);color:var(--md-sys-color-on-surface);flex:0 0 auto}.flow-step-content{min-width:0;display:flex;flex-direction:column;gap:1px}.flow-step-label{font-size:11px;font-weight:700;color:var(--md-sys-color-on-surface)}.flow-step-detail{font-size:11px;color:var(--md-sys-color-on-surface-variant);line-height:1.3}.flow-step.active .flow-step-index{border-color:color-mix(in srgb,var(--md-sys-color-primary) 60%,var(--md-sys-color-outline-variant));background:color-mix(in srgb,var(--md-sys-color-primary-container) 85%,var(--md-sys-color-surface-container-highest));color:var(--md-sys-color-on-primary-container)}.flow-step.done .flow-step-index{border-color:transparent;background:color-mix(in srgb,var(--md-sys-color-primary) 18%,var(--md-sys-color-surface-container-highest))}.task-timeline{margin-top:4px;display:grid;gap:6px}.task-timeline-item{display:flex;align-items:flex-start;gap:8px;border:1px solid var(--md-sys-color-outline-variant);border-radius:10px;padding:6px 8px;background:var(--md-sys-color-surface-container-low);opacity:.76}.task-timeline-item.active{opacity:1;border-color:color-mix(in srgb,var(--md-sys-color-primary) 40%,var(--md-sys-color-outline-variant));background:color-mix(in srgb,var(--md-sys-color-primary-container) 34%,var(--md-sys-color-surface-container-low))}.task-timeline-item.done{opacity:.9;border-color:color-mix(in srgb,var(--md-sys-color-primary) 24%,var(--md-sys-color-outline-variant))}.task-timeline-dot{width:18px;height:18px;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;font-size:10px;font-weight:700;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-highest);color:var(--md-sys-color-on-surface);flex:0 0 auto}.task-timeline-copy{min-width:0;display:flex;flex-direction:column;gap:1px}.task-timeline-title{font-size:11px;font-weight:700;color:var(--md-sys-color-on-surface)}.task-timeline-detail{font-size:11px;line-height:1.3;color:var(--md-sys-color-on-surface-variant)}.clarification-decision-head{display:inline-flex;align-items:center;width:100%;gap:6px;padding:8px 12px 0;box-sizing:border-box}.clarification-decision-index{width:18px;height:18px;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;font-size:10px;font-weight:700;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 35%,var(--md-sys-color-outline-variant));color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary-container) 68%,transparent)}.clarification-decision-type{font-size:10px;letter-spacing:.08em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant);opacity:.92}.clarification-decision-state{font-size:10px;font-weight:700;color:var(--md-sys-color-primary)}.clarification-option{border-color:color-mix(in srgb,var(--md-sys-color-primary) 20%,var(--md-sys-color-outline-variant));background:linear-gradient(145deg,color-mix(in srgb,var(--md-sys-color-primary-container) 16%,transparent),transparent 55%),var(--md-sys-color-surface-container-low)}.clarification-option.selected{border-color:color-mix(in srgb,var(--md-sys-color-primary) 56%,var(--md-sys-color-outline-variant));background:linear-gradient(145deg,color-mix(in srgb,var(--md-sys-color-primary-container) 44%,transparent),transparent 62%),var(--md-sys-color-surface-container);box-shadow:0 8px 16px color-mix(in srgb,var(--md-sys-color-primary) 18%,transparent)}.clarification-options-block{overflow:visible;padding-right:4px}@media(max-width:959px){.assistant-thought-plan-actions{grid-template-columns:1fr}}.ai-assistant-panel{width:min(604px,100vw - 18px)}.assistant-section,.assistant-card{margin:0;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 20%,var(--md-sys-color-outline-variant))}.assistant-section{min-height:0;padding:14px 16px;overflow:visible}.assistant-card{min-height:0;padding:14px 16px 16px;overflow:visible}.suggestions-area,.assistant-history,.loading-suggestions{overflow-y:auto;overflow-x:hidden}.section-header{min-width:0;display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:10px}.section-title{min-width:0;font-size:14px;font-weight:700;line-height:1.35;overflow-wrap:anywhere}.suggestions-actions{flex:0 0 auto;display:inline-flex;align-items:center}.review-area,.error-area,.success-area,.clarification-area{padding:0;overflow-y:auto;overflow-x:hidden;scrollbar-gutter:auto}.review-trust{margin:2px 0 4px}.trust-chip{max-width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.warnings-area,.review-summary,.review-diff,.apply-details,.clarification-options-block,.clarification-manual-toggle{width:100%;max-width:100%;min-width:0}.review-diff{padding:12px 14px}.review-diff-full{padding:10px;overflow-x:auto}.review-diff-block{min-width:0}.review-diff-block pre{overflow-wrap:anywhere;word-break:break-word}.clarification-options-block{padding:4px 2px 10px}.clarification-option{line-height:normal}:host ::ng-deep .clarification-option .mdc-button__label{line-height:1.35!important}.clarification-plain-label{padding:6px 12px 12px;font-size:14px;line-height:1.35}.clarification-manual-toggle{margin-top:10px;padding:10px 2px 0;flex-wrap:wrap;row-gap:6px}.suggestions-content .suggestion-actions{gap:6px}.suggestions-content .suggestion-arrow,.suggestions-content .suggestion-action-btn mat-icon,.suggestions-content .suggestion-arrow mat-icon{display:inline-flex;align-items:center;justify-content:center}:host ::ng-deep .assistant-quick-menu-panel{min-width:244px;max-width:min(90vw,320px);border-radius:14px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 26%,var(--md-sys-color-outline-variant));background:var(--md-sys-color-surface-container-high);box-shadow:0 12px 28px color-mix(in srgb,var(--md-sys-color-shadow, var(--md-sys-color-on-surface)) 32%,transparent),inset 0 1px color-mix(in srgb,var(--md-sys-color-on-surface) 6%,transparent);overflow:hidden;padding:6px}:host ::ng-deep .assistant-quick-menu-panel .mat-mdc-menu-item{min-height:36px;border-radius:10px;color:var(--md-sys-color-on-surface);font-size:12px;font-weight:500;margin:1px 0}:host ::ng-deep .assistant-quick-menu-panel .mat-mdc-menu-item .mat-icon{color:color-mix(in srgb,var(--md-sys-color-on-surface) 82%,var(--md-sys-color-on-surface-variant))}:host ::ng-deep .assistant-quick-menu-panel .mat-mdc-menu-item:hover:not([disabled]){background:color-mix(in srgb,var(--md-sys-color-primary-container) 45%,transparent)}:host ::ng-deep .assistant-quick-menu-panel .mat-mdc-menu-item:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:-2px}:host ::ng-deep .assistant-quick-menu-panel .assistant-quick-menu-danger{color:var(--md-sys-color-error)}:host ::ng-deep .assistant-quick-menu-panel .assistant-quick-menu-danger .mat-icon{color:var(--md-sys-color-error)}@media(max-width:959px){::ng-deep .ai-assistant-overlay-pane{top:12px!important;left:12px!important;width:calc(100vw - 24px)!important;height:calc(100vh - 24px)!important;max-width:calc(100vw - 24px);max-height:calc(100vh - 24px);transform:none!important}.ai-assistant-panel{width:calc(100vw - 48px);min-height:min(620px,100vh - 48px);max-height:calc(100vh - 48px)}.assistant-section,.assistant-card{margin:0}.assistant-card,.assistant-section{padding:12px}}.ai-trigger-btn{--mdc-icon-button-state-layer-size: 36px;width:36px;height:36px;border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-primary) 9%,transparent);border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 22%,transparent);color:var(--md-sys-color-primary);opacity:1}.ai-trigger-btn:hover:not(:disabled){background:color-mix(in srgb,var(--md-sys-color-primary) 16%,transparent);border-color:color-mix(in srgb,var(--md-sys-color-primary) 36%,transparent);color:var(--md-sys-color-on-primary-container)}.ai-trigger-btn:focus-visible,.assistant-close-btn:focus-visible,.assistant-tab:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.assistant-close-btn{width:28px;height:28px;color:var(--md-sys-color-on-surface-variant)}.assistant-close-btn:hover:not(:disabled){background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface)}.assistant-body{padding:12px 16px;overflow:hidden;min-height:0;flex:1;display:flex;flex-direction:column;gap:12px}.assistant-body>*{min-height:0}@media(max-width:959px){.assistant-nav{padding:8px 12px 0}.assistant-body,.assistant-footer{padding:10px 12px}.suggestions-content .suggestion-item{grid-template-columns:1fr;align-items:start}.suggestion-actions{justify-content:flex-start}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.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: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i4.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation", "cdkConnectedOverlayUsePopover", "cdkConnectedOverlayMatchWidth", "cdkConnectedOverlay"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: i4.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "ngmodule", type: A11yModule }, { kind: "directive", type: i5.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i7.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i8.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i15.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["role", "id", "aria-label", "aria-description", "value", "color", "removable", "highlighted", "disableRipple", "disabled"], outputs: ["removed", "destroyed"], exportAs: ["matChip"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i10.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i10.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i10.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: DatePipe, name: "date" }, { kind: "pipe", type: JsonPipe, name: "json" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
7984
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PraxisAiAssistantComponent, isStandalone: true, selector: "praxis-ai-assistant", inputs: { adapter: "adapter", riskPolicy: "riskPolicy", allowManualPatchEdit: "allowManualPatchEdit", hasBackdrop: "hasBackdrop" }, viewQueries: [{ propertyName: "overlayOrigin", first: true, predicate: CdkOverlayOrigin, descendants: true }, { propertyName: "triggerButton", first: true, predicate: ["triggerBtn"], descendants: true, read: ElementRef }, { propertyName: "inputElement", first: true, predicate: ["inputEl"], descendants: true }], ngImport: i0, template: "<!-- Trigger Button -->\n<button\n praxisIconButton=\"auto_awesome\"\n size=\"compact\"\n cdkOverlayOrigin\n #trigger=\"cdkOverlayOrigin\"\n #triggerBtn\n (click)=\"open()\"\n [disabled]=\"isOpen\"\n class=\"ai-trigger-btn\"\n matTooltip=\"Assistente de Configura\u00E7\u00E3o\"\n aria-label=\"Abrir Assistente IA\"></button>\n\n<!-- Overlay Template -->\n<ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"trigger\"\n [cdkConnectedOverlayOpen]=\"isOpen\"\n [cdkConnectedOverlayHasBackdrop]=\"hasBackdrop\"\n [cdkConnectedOverlayPositions]=\"overlayPositions\"\n [cdkConnectedOverlayPush]=\"true\"\n [cdkConnectedOverlayViewportMargin]=\"12\"\n cdkConnectedOverlayPanelClass=\"ai-assistant-overlay-pane\"\n cdkConnectedOverlayBackdropClass=\"ai-assistant-backdrop\"\n (backdropClick)=\"close()\"\n (overlayOutsideClick)=\"close()\"\n (detach)=\"close()\">\n\n <div\n class=\"ai-assistant-panel\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"Assistente de Configura\u00E7\u00E3o\"\n [attr.aria-busy]=\"isBusyState() ? 'true' : null\"\n [cdkTrapFocus]=\"hasBackdrop\"\n [cdkTrapFocusAutoCapture]=\"hasBackdrop\"\n (keydown)=\"onKeydown($event)\"\n >\n\n <!-- HEADER -->\n <div class=\"assistant-header\">\n <div class=\"assistant-header__left\">\n <mat-icon class=\"magic-icon\">auto_awesome</mat-icon>\n <div class=\"assistant-title-group\">\n <div class=\"assistant-title\">Assistente de Configura\u00E7\u00E3o</div>\n <div class=\"assistant-subtitle\">Copiloto contextual para ajustes guiados</div>\n <div class=\"assistant-header-chips\">\n <span\n class=\"mode-chip\"\n [class.mock]=\"mockMode\"\n [matTooltip]=\"mockMode ? 'Sem chave de API: respostas de demonstra\u00E7\u00E3o' : 'Conectado ao assistente configurado'\"\n >\n {{ mockMode ? 'Mock' : 'Conectado' }}\n </span>\n <span\n class=\"policy-chip\"\n [class.strict]=\"isStrictRiskPolicy()\"\n [matTooltip]=\"getRiskPolicyTooltip()\"\n >\n {{ getRiskPolicyLabel() }}\n </span>\n </div>\n </div>\n </div>\n <div class=\"assistant-header__right\">\n <button\n praxisIconButton=\"close\"\n size=\"dense\"\n type=\"button\"\n class=\"assistant-close-btn\"\n (click)=\"close()\"\n aria-label=\"Fechar assistente\"\n matTooltip=\"Fechar assistente\"\n ></button>\n </div>\n </div>\n <div\n class=\"assistant-status\"\n [class.processing]=\"isBusyState()\"\n [class.pending]=\"state === 'clarification'\"\n [class.warning]=\"state === 'error'\"\n [class.success]=\"state === 'review' || state === 'success'\"\n [class.compact]=\"!shouldShowSystemStatusDetail()\"\n role=\"status\"\n [attr.aria-live]=\"getSystemStatusAriaLive()\"\n aria-atomic=\"true\"\n >\n <span class=\"assistant-status-dot\" aria-hidden=\"true\"></span>\n <div class=\"assistant-status-content\">\n <div class=\"assistant-status-label\">\n <span class=\"assistant-status-label-prefix\">Status:</span>\n <span>{{ getSystemStatusLabel() }}</span>\n @if (shouldShowSnapshotFallbackBadge()) {\n <span class=\"assistant-status-mode\">Snapshot</span>\n }\n </div>\n @if (shouldShowSystemStatusDetail()) {\n <div class=\"assistant-status-detail\">{{ getSystemStatusDetail() }}</div>\n }\n </div>\n </div>\n @if (shouldShowTaskFlow()) {\n <div class=\"assistant-flow\" role=\"list\" aria-label=\"Fluxo da proposta\">\n @for (step of flowSteps; track step) {\n <div\n class=\"flow-step\"\n role=\"listitem\"\n [class.active]=\"getFlowStepState(step.step) === 'active'\"\n [class.done]=\"getFlowStepState(step.step) === 'done'\"\n >\n <span class=\"flow-step-index\">{{ step.step }}</span>\n <span class=\"flow-step-content\">\n <span class=\"flow-step-label\">{{ step.label }}</span>\n <span class=\"flow-step-detail\">{{ getFlowStepDetail(step.step) }}</span>\n </span>\n </div>\n }\n </div>\n }\n <div class=\"assistant-nav\">\n <div\n class=\"assistant-tabs\"\n role=\"tablist\"\n aria-label=\"Se\u00E7\u00F5es do assistente\"\n (keydown)=\"onTabsKeydown($event)\"\n >\n @if (isTaskMode()) {\n <button\n class=\"assistant-tab\"\n type=\"button\"\n id=\"assistant-tab-task\"\n role=\"tab\"\n aria-label=\"Proposta atual\"\n [attr.aria-selected]=\"isActiveTab('task')\"\n aria-controls=\"assistant-panel-task\"\n [attr.tabindex]=\"isActiveTab('task') ? 0 : -1\"\n [class.active]=\"isActiveTab('task')\"\n (click)=\"setActiveTab('task')\"\n >\n Proposta\n @if (hasPendingClarification() && !isActiveTab('task')) {\n <span class=\"assistant-tab-badge\">1</span>\n }\n </button>\n }\n <button\n class=\"assistant-tab\"\n type=\"button\"\n id=\"assistant-tab-chat\"\n role=\"tab\"\n aria-label=\"Hist\u00F3rico\"\n [attr.aria-selected]=\"isActiveTab('chat')\"\n aria-controls=\"assistant-panel-chat\"\n [attr.tabindex]=\"isActiveTab('chat') ? 0 : -1\"\n [class.active]=\"isActiveTab('chat')\"\n (click)=\"setActiveTab('chat')\"\n >\n Hist\u00F3rico\n </button>\n <button\n class=\"assistant-tab\"\n type=\"button\"\n id=\"assistant-tab-suggestions\"\n role=\"tab\"\n aria-label=\"Sugest\u00F5es de melhoria\"\n [attr.aria-selected]=\"isActiveTab('suggestions')\"\n aria-controls=\"assistant-panel-suggestions\"\n [attr.tabindex]=\"isActiveTab('suggestions') ? 0 : -1\"\n [class.active]=\"isActiveTab('suggestions')\"\n (click)=\"setActiveTab('suggestions')\"\n >\n Sugest\u00F5es\n </button>\n </div>\n </div>\n\n <!-- BODY: Dynamic Content based on State -->\n <div class=\"assistant-body\">\n @if (shouldShowThoughtCard()) {\n <div class=\"assistant-thought assistant-section\">\n <div class=\"assistant-thought-meta\">\n <mat-icon>psychology</mat-icon>\n <span>{{ getThoughtTimingLabel() }}</span>\n </div>\n <div class=\"assistant-thought-summary\">{{ getThoughtSummary() }}</div>\n <div class=\"assistant-thought-plan\">\n <div class=\"assistant-thought-plan-title\">{{ getThoughtPlanTitle() }}</div>\n <div class=\"assistant-thought-plan-actions\">\n <button\n mat-stroked-button\n type=\"button\"\n class=\"thought-action-details\"\n (click)=\"openThoughtDetails()\"\n [attr.aria-label]=\"getThoughtDetailsLabel()\"\n [matTooltip]=\"getThoughtDetailsTooltip()\"\n >\n {{ getThoughtDetailsLabel() }}\n </button>\n @if (shouldShowThoughtPreviewAction()) {\n <button\n mat-flat-button\n color=\"primary\"\n type=\"button\"\n class=\"thought-action-preview\"\n (click)=\"openThoughtPreview()\"\n [matTooltip]=\"getThoughtPreviewTooltip()\"\n >\n Pr\u00E9via\n </button>\n }\n </div>\n <div class=\"assistant-thought-plan-hint\">{{ getThoughtActionHint() }}</div>\n @if (getThoughtChecklist(); as thoughtChecklist) {\n @if (thoughtChecklist.length) {\n <div class=\"assistant-thought-checklist\">\n @for (item of thoughtChecklist; track item) {\n <div class=\"assistant-thought-checklist-item\">\n <mat-icon>radio_button_unchecked</mat-icon>\n <span>{{ item }}</span>\n </div>\n }\n </div>\n }\n @if (isBusyState() && !thoughtChecklist.length) {\n <div class=\"assistant-thought-shimmer\">\n <div class=\"shimmer-line shimmer-line-1\"></div>\n <div class=\"shimmer-line shimmer-line-2\"></div>\n <div class=\"shimmer-line shimmer-line-3\"></div>\n </div>\n }\n }\n </div>\n </div>\n }\n @if (processingInfoVisible) {\n <div class=\"processing-banner\">\n <mat-spinner diameter=\"16\"></mat-spinner>\n <span>{{ aiExplanation || 'Analisando solicita\u00E7\u00E3o e preparando proposta...' }}</span>\n <button mat-button type=\"button\" class=\"processing-retry\" (click)=\"retryProcessing()\">Tentar novamente</button>\n </div>\n }\n @if (historyContext && isActiveTab('chat')) {\n <div\n class=\"assistant-history assistant-section\"\n id=\"assistant-panel-chat\"\n role=\"tabpanel\"\n aria-labelledby=\"assistant-tab-chat\"\n >\n <div class=\"section-header\">\n <div class=\"section-heading\">\n <div class=\"section-title\">Hist\u00F3rico</div>\n <div class=\"section-subtitle\">Sess\u00F5es recentes, pedidos reaproveit\u00E1veis e desfazer r\u00E1pido.</div>\n </div>\n <div class=\"history-actions\" role=\"group\" aria-label=\"A\u00E7\u00F5es do hist\u00F3rico\">\n <button\n mat-stroked-button\n type=\"button\"\n class=\"history-action-btn\"\n (click)=\"historyExpanded = !historyExpanded\"\n [matTooltip]=\"historyExpanded ? 'Recolher hist\u00F3rico' : 'Expandir hist\u00F3rico'\"\n [attr.aria-label]=\"historyExpanded ? 'Recolher hist\u00F3rico' : 'Expandir hist\u00F3rico'\"\n [disabled]=\"!historyWarnings.length && !historySessions.length && !activeHistoryMessages.length\"\n >\n <mat-icon>{{ historyExpanded ? 'expand_less' : 'expand_more' }}</mat-icon>\n <span>{{ historyExpanded ? 'Recolher' : 'Expandir' }}</span>\n </button>\n <button\n mat-stroked-button\n type=\"button\"\n class=\"history-action-btn\"\n (click)=\"startNewSession()\"\n matTooltip=\"Nova conversa\"\n aria-label=\"Nova conversa\"\n [disabled]=\"isBusyState()\"\n >\n <mat-icon>add_comment</mat-icon>\n <span>Nova conversa</span>\n </button>\n <button\n mat-stroked-button\n type=\"button\"\n (click)=\"clearHistory()\"\n matTooltip=\"Limpar hist\u00F3rico local\"\n aria-label=\"Limpar hist\u00F3rico local\"\n class=\"history-action-btn history-action-btn--danger\"\n [disabled]=\"!historySessions.length\"\n >\n <mat-icon>delete_outline</mat-icon>\n <span>Limpar</span>\n </button>\n </div>\n </div>\n @if (historyUndoDeleteSession) {\n <div class=\"history-undo\">\n <span>Sess\u00E3o removida.</span>\n <button mat-button type=\"button\" (click)=\"undoRemoveHistorySession()\">\n Desfazer\n </button>\n </div>\n }\n @if (historyExpanded && historyWarnings.length) {\n <div class=\"history-warnings\">\n <mat-icon>info</mat-icon>\n <div class=\"history-warnings-list\">\n @for (warning of historyWarnings; track warning) {\n <div>{{ warning }}</div>\n }\n <div class=\"history-warnings-hint\">\n Configure headers via API_CONFIG_STORAGE_OPTIONS no host.\n </div>\n </div>\n </div>\n }\n @if (historyExpanded && historySessions.length) {\n <div class=\"history-sessions\">\n @for (session of historySessions; track session.id) {\n <div\n class=\"history-session\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"selectHistorySession(session.id)\"\n (keydown)=\"onHistorySessionCardKeydown($event, session.id)\"\n [class.active]=\"session.id === activeHistorySession?.id\"\n [matTooltip]=\"getHistorySessionTooltip(session)\"\n [matTooltipDisabled]=\"!session.componentType && !session.componentId\"\n >\n <div class=\"history-session-main\">\n <span class=\"history-session-title\">{{ session.title }}</span>\n <div class=\"history-session-main-right\">\n <span class=\"history-session-time\">{{ session.updatedAt | date:'short' }}</span>\n <div class=\"history-session-tools\">\n <button\n praxisIconButton=\"edit_note\"\n size=\"dense\"\n type=\"button\"\n class=\"history-session-tool\"\n (click)=\"reuseHistorySessionPrompt(session.id, $event)\"\n matTooltip=\"Reusar \u00FAltimo pedido\"\n aria-label=\"Reusar \u00FAltimo pedido\"\n ></button>\n <button\n praxisIconButton=\"delete_outline\"\n size=\"dense\"\n type=\"button\"\n class=\"history-session-tool history-session-tool--danger\"\n (click)=\"removeHistorySession(session.id, $event)\"\n matTooltip=\"Excluir sess\u00E3o\"\n aria-label=\"Excluir sess\u00E3o\"\n ></button>\n </div>\n </div>\n </div>\n <div class=\"history-session-meta\">\n @if (session.componentType) {\n <span class=\"history-chip\">{{ session.componentType }}</span>\n }\n @if (session.componentId) {\n <span class=\"history-chip\">{{ session.componentId }}</span>\n }\n </div>\n </div>\n }\n </div>\n }\n @if (historyExpanded && !historySessions.length) {\n <div class=\"history-empty\">\n Nenhuma sess\u00E3o salva ainda.\n </div>\n }\n @if (historyExpanded && activeHistoryMessages.length) {\n <div class=\"history-messages\">\n @if (activeHistoryTotalMessages > activeHistoryMessages.length) {\n <div\n class=\"history-messages-hint\"\n >\n Mostrando \u00FAltimas {{ activeHistoryMessages.length }} de {{ activeHistoryTotalMessages }} mensagens.\n </div>\n }\n @for (msg of activeHistoryMessages; track msg.id) {\n <div\n class=\"history-message\"\n [class.user]=\"msg.role === 'user'\"\n [class.assistant]=\"msg.role === 'assistant'\"\n >\n <div class=\"history-message-header\">\n <span class=\"history-message-role\">{{ msg.role === 'user' ? 'Voc\u00EA' : 'Assistente' }}</span>\n <span class=\"history-message-time\">{{ msg.createdAt | date:'shortTime' }}</span>\n @if (msg.context?.usedRag) {\n <span\n class=\"history-rag\"\n matTooltip=\"Resposta baseada em contexto recuperado (RAG)\"\n >RAG</span>\n }\n </div>\n <div class=\"history-message-text\">{{ msg.text }}</div>\n </div>\n }\n </div>\n }\n @if (historyExpanded && historySessions.length && !activeHistoryMessages.length) {\n <div class=\"history-empty history-empty--panel\">\n Selecione uma sess\u00E3o para visualizar as mensagens.\n </div>\n }\n @if (historyExpanded) {\n <div class=\"history-helper\">\n O hist\u00F3rico \u00E9 local ao usu\u00E1rio e ao componente atual.\n </div>\n }\n </div>\n }\n\n @if (loadingSuggestions && isActiveTab('suggestions')) {\n <div\n class=\"loading-suggestions assistant-section\"\n id=\"assistant-panel-suggestions\"\n role=\"tabpanel\"\n aria-labelledby=\"assistant-tab-suggestions\"\n >\n <mat-spinner diameter=\"20\"></mat-spinner>\n <span>Carregando sugest\u00F5es de melhoria...</span>\n </div>\n }\n\n <!-- STATE: LISTENING (Suggestions) -->\n @if (state === 'listening' && isActiveTab('suggestions')) {\n <div\n class=\"suggestions-area assistant-section\"\n id=\"assistant-panel-suggestions\"\n role=\"tabpanel\"\n aria-labelledby=\"assistant-tab-suggestions\"\n >\n <div class=\"section-header\">\n <div class=\"section-title\">Sugest\u00F5es de melhoria</div>\n <div class=\"suggestions-actions\">\n <button praxisIconButton=\"refresh\" size=\"dense\" type=\"button\" (click)=\"refreshSuggestions()\" [disabled]=\"loadingSuggestions\" aria-label=\"Atualizar sugest\u00F5es\" matTooltip=\"Atualizar sugest\u00F5es\"></button>\n </div>\n </div>\n @if (!loadingSuggestions) {\n <div class=\"suggestions-hero\">\n <div class=\"suggestions-hero__label\">Contexto ativo</div>\n <div class=\"suggestions-hero__title\">{{ adapter.componentName || 'Componente atual' }}</div>\n <div class=\"suggestions-hero__detail\">{{ getSystemStatusDetail() }}</div>\n </div>\n }\n @if (suggestionsWarnings.length) {\n <div class=\"warnings-area\">\n <mat-icon class=\"warnings-icon\">warning_amber</mat-icon>\n <div class=\"warnings-content\">\n <div class=\"warnings-title\">Avisos</div>\n <div class=\"warnings-list\">\n @for (warning of suggestionsWarnings; track warning) {\n <div>{{ warning }}</div>\n }\n </div>\n </div>\n </div>\n }\n @if (!loadingSuggestions && (richSuggestions.length || hasDismissedSuggestions())) {\n <div class=\"suggestions-content\">\n @if (hasDismissedSuggestions()) {\n <div class=\"suggestions-filter\">\n <span>{{ getDismissedSuggestionCount() }} oculta(s)</span>\n <button mat-button type=\"button\" (click)=\"restoreDismissedSuggestions()\">\n Restaurar\n </button>\n </div>\n }\n @if (getVisibleSuggestions().length) {\n <div class=\"suggestions-list\">\n @for (sug of getVisibleSuggestions(); track sug.id) {\n <div\n class=\"suggestion-item\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'Selecionar sugest\u00E3o: ' + sug.label\"\n (click)=\"selectSuggestion(sug)\"\n (keydown)=\"onSuggestionCardKeydown($event, sug)\"\n >\n <div class=\"suggestion-copy\">\n <div class=\"suggestion-main\">\n @if (sug.icon) {\n <mat-icon class=\"suggestion-icon\">{{ sug.icon }}</mat-icon>\n }\n <span class=\"suggestion-label\">{{ sug.label }}</span>\n @if (sug.group) {\n <span class=\"suggestion-group\">{{ sug.group }}</span>\n }\n </div>\n @if (sug.description) {\n <div class=\"suggestion-desc\">{{ sug.description }}</div>\n }\n </div>\n <div class=\"suggestion-actions\">\n <span class=\"suggestion-arrow\" aria-hidden=\"true\">\n <mat-icon>chevron_right</mat-icon>\n </span>\n <button\n praxisIconButton=\"edit\"\n size=\"dense\"\n type=\"button\"\n class=\"suggestion-action-btn\"\n (click)=\"prepareSuggestionPrompt(sug, $event)\"\n matTooltip=\"Refinar pedido\"\n aria-label=\"Refinar pedido\"\n ></button>\n <button\n praxisIconButton=\"visibility_off\"\n size=\"dense\"\n type=\"button\"\n class=\"suggestion-action-btn suggestion-action-btn--danger\"\n (click)=\"dismissSuggestion(sug, $event)\"\n matTooltip=\"Ocultar sugest\u00E3o\"\n aria-label=\"Ocultar sugest\u00E3o\"\n ></button>\n </div>\n </div>\n }\n </div>\n } @else {\n <div class=\"suggestions-empty suggestions-empty--inline\">\n Todas as sugest\u00F5es foram ocultadas.\n </div>\n }\n </div>\n }\n @if (!loadingSuggestions && !richSuggestions.length) {\n <div class=\"suggestions-empty\">\n Nenhuma sugest\u00E3o dispon\u00EDvel no momento.\n </div>\n }\n @if (!loadingSuggestions && !richSuggestions.length) {\n <div class=\"suggestions-helper\">\n Selecione uma sugest\u00E3o acima ou descreva uma altera\u00E7\u00E3o no campo inferior.\n </div>\n }\n </div>\n }\n\n <!-- STATE: CLARIFICATION (Two-Step Flow) -->\n @if (state === 'clarification' && isActiveTab('task')) {\n <div\n class=\"clarification-area assistant-card\"\n id=\"assistant-panel-task\"\n role=\"tabpanel\"\n aria-labelledby=\"assistant-tab-task\"\n >\n @if (!shouldShowThoughtCard()) {\n <div class=\"task-header\">\n <div class=\"task-title\">{{ getTaskTitle() }}</div>\n <div class=\"task-subtitle\">{{ getTaskSubtitle() }}</div>\n @if (clarificationOptions.length > 1 && getTaskSelectionSummary(); as selectionSummary) {\n <div class=\"task-meta\">\n <span class=\"task-meta-label\">Selecionado:</span>\n <span class=\"task-meta-value\">{{ selectionSummary }}</span>\n </div>\n }\n @if (shouldShowTaskSteps()) {\n <div class=\"task-steps\">\n <span class=\"task-step active\">1 Dados</span>\n <span class=\"task-step\">2 Layout</span>\n <span class=\"task-step\">3 Revis\u00E3o</span>\n </div>\n }\n </div>\n }\n @if (clarificationResponseType === 'context') {\n <div class=\"context-only\">\n <mat-spinner diameter=\"24\"></mat-spinner>\n <div class=\"context-only-hint\">Buscando contexto adicional...</div>\n </div>\n }\n <ng-template #clarificationOptionContent let-opt let-index=\"index\" let-compact=\"compact\">\n @if (!compact) {\n <div class=\"clarification-decision-head\">\n <span class=\"clarification-decision-index\">{{ index + 1 }}</span>\n <span class=\"clarification-decision-type\">{{ getClarificationOptionKindLabel(opt) }}</span>\n <span class=\"spacer\"></span>\n @if (isClarificationSelected(opt)) {\n <span class=\"clarification-decision-state\">Selecionado</span>\n }\n </div>\n }\n @switch (getClarificationOptionLayout(opt)) {\n @case ('endpoint') {\n <div class=\"clarification-card\">\n <div class=\"clarification-card-header\">\n <mat-icon class=\"endpoint-icon\">{{ getEndpointIcon(opt) }}</mat-icon>\n @if (getEndpointMethod(opt); as method) {\n <span class=\"endpoint-method\" [attr.data-method]=\"method\">{{ method }}</span>\n }\n <span class=\"endpoint-label\">{{ opt.label }}</span>\n <span class=\"spacer\"></span>\n <mat-icon class=\"select-indicator\">\n {{ isClarificationSelected(opt) ? 'check_circle' : 'radio_button_unchecked' }}\n </mat-icon>\n </div>\n <div class=\"clarification-card-body\">\n @if (getEndpointPath(opt); as path) {\n <div class=\"endpoint-path\">{{ path }}</div>\n }\n @if (opt.contextHints?.description) {\n <div\n class=\"endpoint-description\"\n [matTooltip]=\"getDescriptionTooltip(opt)\"\n [matTooltipDisabled]=\"!shouldShowDescriptionTooltip(opt)\"\n >\n {{ opt.contextHints?.description }}\n </div>\n }\n </div>\n </div>\n }\n @case ('color') {\n <div class=\"clarification-color\">\n <span\n class=\"color-swatch\"\n [style.background]=\"getSafeHexColor(opt) || 'var(--md-sys-color-surface-container-highest)'\"\n ></span>\n <div class=\"color-meta\">\n <span class=\"color-label\">{{ opt.label }}</span>\n @if (opt.contextHints?.hexColor) {\n <span class=\"color-value\">{{ opt.contextHints?.hexColor }}</span>\n }\n </div>\n </div>\n }\n @case ('description') {\n <div class=\"clarification-description\">\n <span class=\"clarification-label\">{{ opt.label }}</span>\n @if (opt.contextHints?.description) {\n <span\n class=\"clarification-subtitle\"\n [matTooltip]=\"getDescriptionTooltip(opt)\"\n [matTooltipDisabled]=\"!shouldShowDescriptionTooltip(opt)\"\n >\n {{ opt.contextHints?.description }}\n </span>\n }\n </div>\n }\n @default {\n <span class=\"clarification-plain-label\">{{ opt.label }}</span>\n }\n }\n </ng-template>\n @if (warnings.length) {\n <div class=\"warnings-area\">\n <mat-icon class=\"warnings-icon\">warning_amber</mat-icon>\n <div class=\"warnings-content\">\n <div class=\"warnings-title\">Avisos</div>\n <div class=\"warnings-list\">\n @for (warning of warnings; track warning) {\n <div>{{ warning }}</div>\n }\n </div>\n </div>\n </div>\n }\n @if (clarificationQuestions.length) {\n <div\n class=\"clarification-questions\"\n [class.attention-highlight]=\"highlightClarificationDetails && !clarificationOptions.length\"\n >\n @for (question of clarificationQuestions; track question; let i = $index) {\n <div class=\"clarification-question\">\n <div class=\"clarification-question-label\">{{ question }}</div>\n <input\n type=\"text\"\n [(ngModel)]=\"clarificationAnswers[i]\"\n [placeholder]=\"'Resposta ' + (i + 1)\"\n autocomplete=\"off\">\n </div>\n }\n </div>\n }\n @if (clarificationOptions.length) {\n <div\n class=\"clarification-options-block\"\n [class.attention-highlight]=\"highlightClarificationDetails\"\n >\n <div class=\"clarification-options-title\">\n {{ clarificationOptions.length === 1 ? 'Decis\u00E3o sugerida' : 'Decis\u00F5es sugeridas' }}\n </div>\n @if (clarificationOptions.length === 1) {\n <div class=\"clarification-options-hint\">\n Etapa 2 de 4: confirme a melhor op\u00E7\u00E3o para continuar.\n </div>\n }\n @if (clarificationOptions.length > 1) {\n <div class=\"clarification-options-hint\">\n Etapa 2 de 4: selecione a alternativa mais aderente para gerar a proposta.\n </div>\n }\n @if (clarificationResponseType === 'confirm') {\n <div\n class=\"clarification-buttons\"\n [class.list]=\"clarificationPresentation === 'list'\"\n >\n @for (opt of clarificationOptions; track opt.value; let i = $index) {\n <button\n mat-button\n type=\"button\"\n (click)=\"onClarificationOptionClick(opt)\"\n class=\"clarification-option\"\n [class.selected]=\"isClarificationSelected(opt)\"\n [matTooltip]=\"getClarificationTooltip(opt)\"\n [matTooltipDisabled]=\"!shouldShowClarificationTooltip(opt) || isEndpointOption(opt)\"\n >\n <ng-container *ngTemplateOutlet=\"clarificationOptionContent; context: { $implicit: opt, index: i, compact: false }\"></ng-container>\n </button>\n }\n </div>\n }\n @if (clarificationSelectionMode === 'multiple') {\n <div\n class=\"clarification-buttons\"\n [class.list]=\"clarificationPresentation === 'list'\"\n >\n @for (opt of clarificationOptions; track opt.value; let i = $index) {\n <button\n mat-button\n type=\"button\"\n (click)=\"onClarificationOptionClick(opt)\"\n [class.selected]=\"isClarificationSelected(opt)\"\n class=\"clarification-option\"\n [matTooltip]=\"getClarificationTooltip(opt)\"\n [matTooltipDisabled]=\"!shouldShowClarificationTooltip(opt) || isEndpointOption(opt)\"\n >\n <ng-container *ngTemplateOutlet=\"clarificationOptionContent; context: { $implicit: opt, index: i, compact: false }\"></ng-container>\n </button>\n }\n </div>\n }\n @if (clarificationResponseType !== 'confirm' && clarificationSelectionMode === 'single' && clarificationPresentation !== 'chips') {\n <div\n class=\"clarification-buttons\"\n [class.list]=\"clarificationPresentation === 'list'\"\n >\n @for (opt of clarificationOptions; track opt.value; let i = $index) {\n <button\n mat-button\n type=\"button\"\n (click)=\"onClarificationOptionClick(opt)\"\n class=\"clarification-option\"\n [class.selected]=\"isClarificationSelected(opt)\"\n [matTooltip]=\"getClarificationTooltip(opt)\"\n [matTooltipDisabled]=\"!shouldShowClarificationTooltip(opt) || isEndpointOption(opt)\"\n >\n <ng-container *ngTemplateOutlet=\"clarificationOptionContent; context: { $implicit: opt, index: i, compact: false }\"></ng-container>\n </button>\n }\n </div>\n }\n @if (clarificationResponseType !== 'confirm' && clarificationSelectionMode === 'single' && clarificationPresentation === 'chips') {\n <div\n class=\"clarification-chips\"\n >\n @for (opt of clarificationOptions; track opt.value; let i = $index) {\n @if (isEndpointOption(opt)) {\n <button\n mat-button\n type=\"button\"\n class=\"clarification-option clarification-card-button\"\n (click)=\"onClarificationOptionClick(opt)\"\n [class.selected]=\"isClarificationSelected(opt)\"\n [matTooltip]=\"getClarificationTooltip(opt)\"\n [matTooltipDisabled]=\"!shouldShowClarificationTooltip(opt) || isEndpointOption(opt)\"\n >\n <ng-container *ngTemplateOutlet=\"clarificationOptionContent; context: { $implicit: opt, index: i, compact: false }\"></ng-container>\n </button>\n } @else {\n <mat-chip\n (click)=\"onClarificationOptionClick(opt)\"\n [matTooltip]=\"getClarificationTooltip(opt)\"\n [matTooltipDisabled]=\"!shouldShowClarificationTooltip(opt)\"\n class=\"clarification-chip\"\n >\n <ng-container *ngTemplateOutlet=\"clarificationOptionContent; context: { $implicit: opt, index: i, compact: true }\"></ng-container>\n </mat-chip>\n }\n }\n </div>\n }\n </div>\n }\n @if (clarificationAllowCustom && clarificationResponseType !== 'context') {\n <div\n class=\"clarification-manual-toggle\"\n >\n <span class=\"clarification-manual-label\">N\u00E3o encontrou o recurso?</span>\n <button mat-button type=\"button\" (click)=\"toggleManualInput()\">\n {{ showManualInput ? 'Ocultar resposta manual' : 'Responder manualmente' }}\n </button>\n </div>\n }\n @if (clarificationAllowCustom && showManualInput && clarificationResponseType !== 'context') {\n <div\n class=\"clarification-free\"\n >\n <input\n type=\"text\"\n [(ngModel)]=\"clarificationFreeText\"\n placeholder=\"Digite sua resposta\u2026\"\n autocomplete=\"off\"\n (keydown.enter)=\"confirmTaskAction()\"\n />\n </div>\n }\n @if (clarificationAllowCustom && showManualInput && clarificationResponseType !== 'context') {\n <div\n class=\"clarification-free-hint\"\n >\n Pressione Enter para enviar.\n </div>\n }\n </div>\n }\n\n <!-- STATE: REVIEW (Diff/Explanation) -->\n @if (state === 'review' && isActiveTab('task')) {\n <div\n class=\"review-area assistant-card\"\n id=\"assistant-panel-task\"\n role=\"tabpanel\"\n aria-labelledby=\"assistant-tab-task\"\n >\n @if (!shouldShowThoughtCard()) {\n <div class=\"task-header\">\n <div class=\"task-title\">{{ getTaskTitle() }}</div>\n <div class=\"task-subtitle\">{{ getTaskSubtitle() }}</div>\n @if (clarificationOptions.length > 1 && getTaskSelectionSummary(); as selectionSummary) {\n <div class=\"task-meta\">\n <span class=\"task-meta-label\">Selecionado:</span>\n <span class=\"task-meta-value\">{{ selectionSummary }}</span>\n </div>\n }\n @if (shouldShowTaskSteps()) {\n <div class=\"task-steps\">\n <span class=\"task-step\">1 Dados</span>\n <span class=\"task-step\">2 Layout</span>\n <span class=\"task-step active\">3 Revis\u00E3o</span>\n </div>\n }\n </div>\n }\n @if (warnings.length) {\n <div class=\"warnings-area\">\n <mat-icon class=\"warnings-icon\">warning_amber</mat-icon>\n <div class=\"warnings-content\">\n <div class=\"warnings-title\">Avisos</div>\n <div class=\"warnings-list\">\n @for (warning of warnings; track warning) {\n <div>{{ warning }}</div>\n }\n </div>\n </div>\n </div>\n }\n <div class=\"review-trust\">\n <span class=\"trust-chip\" [matTooltip]=\"getScopeTooltip()\">{{ getScopeLabel() }}</span>\n <span class=\"trust-chip\" [matTooltip]=\"getConfidenceTooltip()\">{{ getConfidenceLabel() }}</span>\n <span class=\"trust-chip risk-chip\" [class.medium]=\"getReviewRiskLevel() === 'm\u00E9dio'\" [class.high]=\"getReviewRiskLevel() === 'alto'\">\n Risco {{ getReviewRiskLevel() }}\n </span>\n </div>\n <div class=\"review-summary\" [class.attention-highlight]=\"highlightReviewDetails\">\n <div class=\"review-summary-title\">Resumo da proposta</div>\n <div class=\"review-summary-line\">{{ getReviewSummary() }}</div>\n </div>\n <div class=\"review-diff\">\n <div class=\"review-diff-title\">Pr\u00E9via de mudan\u00E7as</div>\n @if (pendingDiff.length) {\n <div class=\"review-diff-summary\">\n @for (line of getDiffSummaryLines(); track line) {\n <div class=\"review-diff-line\">{{ line }}</div>\n }\n @if (pendingDiff.length > 3) {\n <div class=\"review-diff-more\">\u2026 +{{ pendingDiff.length - 3 }} mudan\u00E7as</div>\n }\n </div>\n <button mat-stroked-button type=\"button\" class=\"review-diff-toggle\" (click)=\"toggleFullDiff()\">\n {{ getDiffToggleLabel() }}\n </button>\n } @else {\n <div class=\"review-diff-empty\">\n N\u00E3o foi poss\u00EDvel gerar um diff estruturado. Revise o resumo e aplique com cautela.\n </div>\n }\n @if (showFullDiff && pendingDiff.length) {\n <div class=\"review-diff-full\">\n @for (diff of pendingDiff; track diff.path) {\n <div class=\"review-diff-block\">\n <div class=\"review-diff-path\">{{ diff.path }}</div>\n <div class=\"review-diff-label\">Antes:</div>\n <pre>{{ diff.before | json }}</pre>\n <div class=\"review-diff-label\">Depois:</div>\n <pre>{{ diff.after | json }}</pre>\n </div>\n }\n </div>\n }\n </div>\n @if (aiExplanation.trim()) {\n <div class=\"ai-explanation\">\n {{ aiExplanation }}\n </div>\n }\n </div>\n }\n\n <!-- STATE: ERROR -->\n @if (state === 'error' && (isActiveTab('task') || (!isTaskMode() && isActiveTab('suggestions')))) {\n <div\n class=\"error-area assistant-card\"\n [attr.id]=\"isTaskMode() ? 'assistant-panel-task' : 'assistant-panel-suggestions'\"\n role=\"tabpanel\"\n [attr.aria-labelledby]=\"isTaskMode() ? 'assistant-tab-task' : 'assistant-tab-suggestions'\"\n >\n <div class=\"error-msg\">\n <mat-icon color=\"warn\">error_outline</mat-icon>\n <span>{{ errorMsg }}</span>\n </div>\n @if (warnings.length) {\n <div class=\"warnings-area\">\n <mat-icon class=\"warnings-icon\">warning_amber</mat-icon>\n <div class=\"warnings-content\">\n <div class=\"warnings-title\">Avisos</div>\n <div class=\"warnings-list\">\n @for (warning of warnings; track warning) {\n <div>{{ warning }}</div>\n }\n </div>\n </div>\n </div>\n }\n @if (shouldShowApplyDetails()) {\n <div class=\"apply-details\">\n <div class=\"apply-details-header\">\n <div class=\"apply-details-title\">Detalhes da aplica\u00E7\u00E3o</div>\n @if (allowManualPatchEdit) {\n <div class=\"apply-details-actions\">\n <button mat-button type=\"button\" (click)=\"togglePatchPathEditor()\" [disabled]=\"!pendingPatch\">\n {{ patchPathEditorExpanded ? 'Ocultar paths' : 'Editar por path' }}\n </button>\n <button mat-button type=\"button\" (click)=\"togglePatchEditor()\" [disabled]=\"!pendingPatch\">\n {{ patchEditorExpanded ? 'Ocultar editor' : 'Editar patch' }}\n </button>\n </div>\n }\n </div>\n @if (lastApplyAt) {\n <div class=\"apply-details-meta\">\n \u00DAltima tentativa: {{ lastApplyAt | date:'short' }}\n </div>\n }\n @if (getApplyPaths().length) {\n <div class=\"apply-paths\">\n @for (path of getApplyPaths(); track path) {\n <span class=\"apply-path-chip\">{{ path }}</span>\n }\n </div>\n }\n @if (applyWarnings.length) {\n <div class=\"apply-warnings\">\n <div class=\"apply-warnings-title\">Avisos da aplica\u00E7\u00E3o</div>\n <div class=\"apply-warnings-list\">\n @for (warning of applyWarnings; track warning) {\n <div>{{ warning }}</div>\n }\n </div>\n </div>\n }\n @if (allowManualPatchEdit && patchPathEditorExpanded) {\n <div class=\"patch-path-editor\">\n <div class=\"patch-editor-label\">Editar por path</div>\n <div class=\"patch-editor-hint\">Texto simples vira string; para for\u00E7ar texto em true/false/n\u00FAmero, use aspas.</div>\n @if (!getEditablePatchPathEdits().length) {\n <div class=\"patch-path-editor-empty\">\n Nenhum path edit\u00E1vel dispon\u00EDvel para este patch.\n </div>\n }\n @if (getEditablePatchPathEdits().length) {\n <div class=\"patch-path-rows\">\n @for (edit of getEditablePatchPathEdits(); track edit.path; let i = $index) {\n <div class=\"patch-path-row\">\n <div class=\"patch-path-label\">{{ edit.path }}</div>\n <input\n type=\"text\"\n [(ngModel)]=\"patchPathEdits[i].valueText\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n />\n @if (patchPathEdits[i].error) {\n <div class=\"patch-editor-error\">{{ patchPathEdits[i].error }}</div>\n }\n </div>\n }\n </div>\n }\n @if (patchPathEditorError) {\n <div class=\"patch-editor-error\">{{ patchPathEditorError }}</div>\n }\n <div class=\"patch-editor-actions\">\n <button mat-button type=\"button\" (click)=\"resetPatchPathEdits()\">\n Restaurar valores\n </button>\n <button mat-button type=\"button\" (click)=\"applyPathEditsToPatch()\">\n Aplicar no patch\n </button>\n <button mat-flat-button color=\"primary\" type=\"button\" (click)=\"reapplyPathEdits()\">\n Reaplicar por path\n </button>\n </div>\n </div>\n }\n @if (allowManualPatchEdit && patchEditorExpanded) {\n <div class=\"patch-editor\">\n <label class=\"patch-editor-label\">Patch JSON</label>\n <textarea\n [(ngModel)]=\"patchEditorText\"\n spellcheck=\"false\"\n ></textarea>\n @if (patchEditorError) {\n <div class=\"patch-editor-error\">{{ patchEditorError }}</div>\n }\n <div class=\"patch-editor-actions\">\n <button mat-button type=\"button\" (click)=\"resetPatchEditor()\">\n Restaurar original\n </button>\n <button mat-flat-button color=\"primary\" type=\"button\" (click)=\"reapplyEditedPatch()\">\n Reaplicar patch\n </button>\n </div>\n </div>\n }\n </div>\n }\n <div class=\"review-actions\">\n <button mat-button (click)=\"close()\">Fechar</button>\n <button mat-stroked-button (click)=\"retry()\">Tentar Novamente</button>\n </div>\n </div>\n }\n\n <!-- STATE: SUCCESS -->\n @if (state === 'success' && (isActiveTab('task') || (!isTaskMode() && isActiveTab('suggestions')))) {\n <div\n class=\"success-area assistant-card\"\n [attr.id]=\"isTaskMode() ? 'assistant-panel-task' : 'assistant-panel-suggestions'\"\n role=\"tabpanel\"\n [attr.aria-labelledby]=\"isTaskMode() ? 'assistant-tab-task' : 'assistant-tab-suggestions'\"\n >\n <div class=\"success-msg\">\n <mat-icon class=\"success-icon\">check_circle</mat-icon>\n <span>{{ aiExplanation || 'Configura\u00E7\u00E3o atualizada.' }}</span>\n </div>\n @if (warnings.length) {\n <div class=\"warnings-area\">\n <mat-icon class=\"warnings-icon\">warning_amber</mat-icon>\n <div class=\"warnings-content\">\n <div class=\"warnings-title\">Avisos</div>\n <div class=\"warnings-list\">\n @for (warning of warnings; track warning) {\n <div>{{ warning }}</div>\n }\n </div>\n </div>\n </div>\n }\n @if (shouldShowApplyDetails()) {\n <div class=\"apply-details\">\n <div class=\"apply-details-header\">\n <div class=\"apply-details-title\">Detalhes da aplica\u00E7\u00E3o</div>\n @if (allowManualPatchEdit) {\n <div class=\"apply-details-actions\">\n <button mat-button type=\"button\" (click)=\"togglePatchPathEditor()\" [disabled]=\"!pendingPatch\">\n {{ patchPathEditorExpanded ? 'Ocultar paths' : 'Editar por path' }}\n </button>\n <button mat-button type=\"button\" (click)=\"togglePatchEditor()\" [disabled]=\"!pendingPatch\">\n {{ patchEditorExpanded ? 'Ocultar editor' : 'Editar e reaplicar' }}\n </button>\n </div>\n }\n </div>\n @if (lastApplyAt) {\n <div class=\"apply-details-meta\">\n Aplicado em {{ lastApplyAt | date:'short' }}\n </div>\n }\n @if (getApplyPaths().length) {\n <div class=\"apply-paths\">\n @for (path of getApplyPaths(); track path) {\n <span class=\"apply-path-chip\">{{ path }}</span>\n }\n </div>\n }\n @if (applyWarnings.length) {\n <div class=\"apply-warnings\">\n <div class=\"apply-warnings-title\">Avisos da aplica\u00E7\u00E3o</div>\n <div class=\"apply-warnings-list\">\n @for (warning of applyWarnings; track warning) {\n <div>{{ warning }}</div>\n }\n </div>\n </div>\n }\n @if (allowManualPatchEdit && patchPathEditorExpanded) {\n <div class=\"patch-path-editor\">\n <div class=\"patch-editor-label\">Editar por path</div>\n <div class=\"patch-editor-hint\">Texto simples vira string; para for\u00E7ar texto em true/false/n\u00FAmero, use aspas.</div>\n @if (!getEditablePatchPathEdits().length) {\n <div class=\"patch-path-editor-empty\">\n Nenhum path edit\u00E1vel dispon\u00EDvel para este patch.\n </div>\n }\n @if (getEditablePatchPathEdits().length) {\n <div class=\"patch-path-rows\">\n @for (edit of getEditablePatchPathEdits(); track edit.path; let i = $index) {\n <div class=\"patch-path-row\">\n <div class=\"patch-path-label\">{{ edit.path }}</div>\n <input\n type=\"text\"\n [(ngModel)]=\"patchPathEdits[i].valueText\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n />\n @if (patchPathEdits[i].error) {\n <div class=\"patch-editor-error\">{{ patchPathEdits[i].error }}</div>\n }\n </div>\n }\n </div>\n }\n @if (patchPathEditorError) {\n <div class=\"patch-editor-error\">{{ patchPathEditorError }}</div>\n }\n <div class=\"patch-editor-actions\">\n <button mat-button type=\"button\" (click)=\"resetPatchPathEdits()\">\n Restaurar valores\n </button>\n <button mat-button type=\"button\" (click)=\"applyPathEditsToPatch()\">\n Aplicar no patch\n </button>\n <button mat-flat-button color=\"primary\" type=\"button\" (click)=\"reapplyPathEdits()\">\n Reaplicar por path\n </button>\n </div>\n </div>\n }\n @if (allowManualPatchEdit && patchEditorExpanded) {\n <div class=\"patch-editor\">\n <label class=\"patch-editor-label\">Patch JSON</label>\n <textarea\n [(ngModel)]=\"patchEditorText\"\n spellcheck=\"false\"\n ></textarea>\n @if (patchEditorError) {\n <div class=\"patch-editor-error\">{{ patchEditorError }}</div>\n }\n <div class=\"patch-editor-actions\">\n <button mat-button type=\"button\" (click)=\"resetPatchEditor()\">\n Restaurar original\n </button>\n <button mat-flat-button color=\"primary\" type=\"button\" (click)=\"reapplyEditedPatch()\">\n Reaplicar patch\n </button>\n </div>\n </div>\n }\n </div>\n }\n <button mat-button color=\"warn\" (click)=\"undoLastChange()\">\n <mat-icon>undo</mat-icon> Desfazer\n </button>\n </div>\n }\n\n </div>\n\n <div class=\"assistant-footer\">\n @if (!isTaskMode()) {\n <button\n praxisIconButton=\"add\"\n size=\"dense\"\n type=\"button\"\n class=\"composer-leading composer-leading-btn\"\n [matMenuTriggerFor]=\"assistantQuickMenu\"\n aria-label=\"Abrir a\u00E7\u00F5es r\u00E1pidas\"\n matTooltip=\"A\u00E7\u00F5es r\u00E1pidas\"\n ></button>\n <input\n #inputEl\n type=\"text\"\n [(ngModel)]=\"userPrompt\"\n [disabled]=\"state === 'processing' || state === 'applying'\"\n placeholder=\"Descreva a altera\u00E7\u00E3o que deseja aplicar\u2026\"\n autocomplete=\"off\"\n />\n <div class=\"send-actions\">\n @if (state === 'listening') {\n <button\n praxisIconButton=\"arrow_upward\"\n size=\"compact\"\n [appearance]=\"userPrompt.trim() ? 'filled' : 'plain'\"\n class=\"send-btn\"\n (click)=\"submitPrompt()\"\n [disabled]=\"!userPrompt.trim()\"\n [class.ready]=\"!!userPrompt.trim()\"\n aria-label=\"Enviar pedido\"\n ></button>\n }\n @if (state === 'processing' || state === 'applying') {\n <mat-spinner diameter=\"20\"></mat-spinner>\n }\n </div>\n } @else {\n <div class=\"task-footer\">\n <div class=\"task-footer-left\">\n <button mat-button type=\"button\" (click)=\"handleTaskSecondary()\">{{ getTaskCancelLabel() }}</button>\n @if (state === 'review') {\n <button\n mat-stroked-button\n type=\"button\"\n (click)=\"retry()\"\n >\n {{ getTaskSecondaryLabel() }}\n </button>\n }\n </div>\n <div class=\"task-footer-right\">\n <button\n class=\"task-primary-btn\"\n mat-flat-button\n color=\"primary\"\n type=\"button\"\n (click)=\"confirmTaskAction()\"\n [disabled]=\"isTaskPrimaryDisabled()\"\n >\n {{ getTaskPrimaryLabel() }}\n </button>\n @if (state === 'processing' || state === 'applying') {\n <mat-spinner diameter=\"20\"></mat-spinner>\n }\n </div>\n </div>\n }\n </div>\n\n <mat-menu #assistantQuickMenu=\"matMenu\" panelClass=\"assistant-quick-menu-panel\">\n <button mat-menu-item type=\"button\" (click)=\"setActiveTab('chat')\">\n <mat-icon>history</mat-icon>\n <span>Hist\u00F3rico</span>\n </button>\n <button mat-menu-item type=\"button\" (click)=\"setActiveTab('suggestions')\">\n <mat-icon>lightbulb</mat-icon>\n <span>Sugest\u00F5es</span>\n </button>\n <button mat-menu-item type=\"button\" (click)=\"startNewSession()\">\n <mat-icon>add_comment</mat-icon>\n <span>Nova conversa</span>\n </button>\n <button mat-menu-item type=\"button\" (click)=\"refreshSuggestions()\" [disabled]=\"loadingSuggestions\">\n <mat-icon>refresh</mat-icon>\n <span>Atualizar sugest\u00F5es</span>\n </button>\n <button\n mat-menu-item\n type=\"button\"\n (click)=\"restoreDismissedSuggestions()\"\n [disabled]=\"!hasDismissedSuggestions()\"\n >\n <mat-icon>visibility</mat-icon>\n <span>Restaurar sugest\u00F5es ocultas</span>\n </button>\n <button\n mat-menu-item\n type=\"button\"\n class=\"assistant-quick-menu-danger\"\n (click)=\"clearHistory()\"\n [disabled]=\"!historySessions.length\"\n >\n <mat-icon>delete_outline</mat-icon>\n <span>Limpar hist\u00F3rico local</span>\n </button>\n </mat-menu>\n </div>\n\n</ng-template>\n", styles: ["@keyframes assistantPremiumEnter{0%{opacity:0;transform:translate(14px) scale(.99)}to{opacity:1;transform:translate(0) scale(1)}}:host ::ng-deep .ai-assistant-backdrop{background:color-mix(in srgb,var(--md-sys-color-scrim, var(--md-sys-color-shadow, var(--md-sys-color-on-surface))) 42%,transparent);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}::ng-deep .ai-assistant-overlay-pane{max-width:calc(100vw - 24px);max-height:calc(100vh - 24px)}.ai-assistant-panel{box-sizing:border-box;width:min(604px,100vw - 18px);min-height:min(620px,100vh - 18px);max-height:min(820px,100vh - 18px);display:flex;flex-direction:column;overflow:hidden;color:var(--md-sys-color-on-surface);border-left:1px solid color-mix(in srgb,var(--md-sys-color-primary) 24%,var(--md-sys-color-outline-variant));border-top:1px solid color-mix(in srgb,var(--md-sys-color-primary) 18%,var(--md-sys-color-outline-variant));border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-primary) 18%,var(--md-sys-color-outline-variant));box-shadow:0 18px 48px color-mix(in srgb,var(--md-sys-color-shadow, var(--md-sys-color-on-surface)) 42%,transparent),inset 0 1px color-mix(in srgb,var(--md-sys-color-on-surface) 10%,transparent);background:radial-gradient(circle at 14% 8%,color-mix(in srgb,var(--md-sys-color-primary-container) 38%,transparent) 0%,transparent 44%),linear-gradient(165deg,color-mix(in srgb,var(--md-sys-color-surface-container-highest) 88%,var(--md-sys-color-surface)),var(--md-sys-color-surface));animation:assistantPremiumEnter .24s cubic-bezier(.22,1,.36,1)}.assistant-header{position:relative;display:flex;align-items:flex-start;justify-content:space-between;gap:12px;padding:12px 16px 10px;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-primary) 18%,var(--md-sys-color-outline-variant));background:linear-gradient(130deg,color-mix(in srgb,var(--md-sys-color-primary-container) 28%,transparent) 0%,transparent 52%),var(--md-sys-color-surface-container-low)}.assistant-header:after{content:\"\";position:absolute;left:16px;right:16px;bottom:-1px;height:1px;background:linear-gradient(90deg,color-mix(in srgb,var(--md-sys-color-primary) 55%,transparent),transparent);pointer-events:none}.assistant-header .assistant-header__left{min-width:0;display:flex;align-items:flex-start;gap:12px}.assistant-header .magic-icon{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;width:30px;height:30px;font-size:18px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 30%,transparent);box-shadow:0 4px 12px color-mix(in srgb,var(--md-sys-color-primary) 26%,transparent)}.assistant-header .assistant-title-group{min-width:0;display:flex;flex-direction:column;gap:4px}.assistant-header .assistant-title{font-size:15px;font-weight:700;letter-spacing:.01em;overflow-wrap:anywhere}.assistant-header .assistant-subtitle{display:block;font-size:11px;line-height:1.25;color:color-mix(in srgb,var(--md-sys-color-on-surface) 70%,var(--md-sys-color-on-surface-variant));overflow-wrap:anywhere}.assistant-header-chips{display:inline-flex;align-items:center;flex-wrap:wrap;gap:6px}.assistant-header .mode-chip{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:999px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 28%,var(--md-sys-color-outline-variant));background:color-mix(in srgb,var(--md-sys-color-primary-container) 64%,var(--md-sys-color-surface-container));color:color-mix(in srgb,var(--md-sys-color-on-primary-container) 85%,var(--md-sys-color-on-surface));font-size:10px;font-weight:700;letter-spacing:.04em;text-transform:uppercase}.assistant-header .mode-chip:before{content:\"\";width:6px;height:6px;border-radius:999px;background:currentColor;box-shadow:0 0 0 3px color-mix(in srgb,currentColor 16%,transparent)}.assistant-header .mode-chip.mock{border-color:color-mix(in srgb,var(--md-sys-color-error) 34%,var(--md-sys-color-outline-variant));background:color-mix(in srgb,var(--md-sys-color-error-container) 72%,var(--md-sys-color-surface-container));color:color-mix(in srgb,var(--md-sys-color-on-error-container) 85%,var(--md-sys-color-error))}.assistant-header .policy-chip{padding:2px 8px;border-radius:999px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 84%,transparent);background:var(--md-sys-color-surface-container-high);font-size:10px;letter-spacing:.02em;font-weight:600}.assistant-header .policy-chip.strict{border-color:color-mix(in srgb,var(--md-sys-color-primary) 42%,var(--md-sys-color-outline-variant));background:color-mix(in srgb,var(--md-sys-color-primary-container) 56%,var(--md-sys-color-surface-container-high))}.assistant-status{display:flex;align-items:flex-start;gap:10px;padding:10px 16px;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-primary) 18%,var(--md-sys-color-outline-variant));border-radius:0;background:linear-gradient(160deg,color-mix(in srgb,var(--md-sys-color-primary-container) 24%,transparent),transparent 48%),var(--md-sys-color-surface-container-low)}.assistant-status-dot{width:8px;height:8px;margin-top:6px;border-radius:999px;flex:0 0 auto;background:var(--md-sys-color-primary);box-shadow:0 0 0 4px color-mix(in srgb,var(--md-sys-color-primary) 16%,transparent)}.assistant-status.warning .assistant-status-dot{background:var(--md-sys-color-error);box-shadow:0 0 0 4px color-mix(in srgb,var(--md-sys-color-error) 16%,transparent)}.assistant-status.success .assistant-status-dot{background:color-mix(in srgb,var(--md-sys-color-primary) 74%,var(--md-sys-color-tertiary, var(--md-sys-color-primary)))}.assistant-status-content{min-width:0;display:flex;flex-direction:column;gap:2px}.assistant-status-label{display:flex;align-items:center;flex-wrap:wrap;gap:4px;font-size:12px;font-weight:700;line-height:1.35}.assistant-status-detail{font-size:11px;line-height:1.4;color:var(--md-sys-color-on-surface-variant);overflow-wrap:anywhere}.assistant-status-mode{padding:1px 6px;border-radius:999px;background:color-mix(in srgb,var(--md-sys-color-primary-container) 72%,transparent);color:var(--md-sys-color-on-primary-container);font-size:10px;font-weight:700}.assistant-nav{padding:8px 16px 0}.assistant-nav .assistant-tabs{display:flex;align-items:center;gap:4px;border-radius:12px;padding:5px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 24%,var(--md-sys-color-outline-variant));border-color:color-mix(in srgb,var(--md-sys-color-primary) 24%,var(--md-sys-color-outline-variant));background:linear-gradient(155deg,color-mix(in srgb,var(--md-sys-color-primary-container) 14%,transparent),transparent 58%),var(--md-sys-color-surface-container-low)}.assistant-nav .assistant-tab{appearance:none;min-width:0;min-height:30px;border:0;border-radius:8px;padding:0 10px;background:transparent;color:var(--md-sys-color-on-surface-variant);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;flex:1 1 0;font-size:11px;font-weight:700;letter-spacing:.01em}.assistant-nav .assistant-tab.active{background:var(--md-sys-color-surface-container-highest);color:var(--md-sys-color-on-surface);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--md-sys-color-primary) 34%,transparent),0 6px 12px color-mix(in srgb,var(--md-sys-color-primary) 18%,transparent)}.assistant-section,.assistant-card{border-radius:14px;border-color:color-mix(in srgb,var(--md-sys-color-primary) 20%,var(--md-sys-color-outline-variant));background:linear-gradient(160deg,color-mix(in srgb,var(--md-sys-color-primary-container) 16%,transparent),transparent 50%),var(--md-sys-color-surface-container-lowest);box-shadow:0 6px 18px color-mix(in srgb,var(--md-sys-color-shadow, var(--md-sys-color-on-surface)) 12%,transparent),inset 0 1px color-mix(in srgb,var(--md-sys-color-on-surface) 7%,transparent)}.suggestions-hero{margin:2px 0 4px;padding:10px 12px;border-radius:12px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 24%,var(--md-sys-color-outline-variant));background:linear-gradient(120deg,color-mix(in srgb,var(--md-sys-color-primary-container) 34%,transparent) 0%,transparent 52%),var(--md-sys-color-surface-container-low)}.suggestions-hero__label{font-size:10px;letter-spacing:.08em;text-transform:uppercase;font-weight:700;color:var(--md-sys-color-on-surface-variant);opacity:.88}.suggestions-hero__title{margin-top:2px;font-size:13px;font-weight:700;color:var(--md-sys-color-on-surface)}.suggestions-hero__detail{margin-top:4px;font-size:12px;line-height:1.4;color:color-mix(in srgb,var(--md-sys-color-on-surface) 78%,var(--md-sys-color-on-surface-variant))}.suggestions-content .suggestion-item{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:12px;padding:12px;border-radius:12px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 18%,var(--md-sys-color-outline-variant));border-color:color-mix(in srgb,var(--md-sys-color-primary) 18%,var(--md-sys-color-outline-variant));background:linear-gradient(140deg,color-mix(in srgb,var(--md-sys-color-primary-container) 16%,transparent),transparent 56%),var(--md-sys-color-surface-container-lowest);transition:transform .2s cubic-bezier(.25,.8,.25,1),border-color .2s ease,box-shadow .2s ease}.suggestions-list{display:flex;flex-direction:column;gap:10px}.suggestion-copy{min-width:0;display:grid;gap:4px}.suggestion-main{min-width:0;display:flex;align-items:center;flex-wrap:wrap;gap:8px}.suggestion-icon{width:18px;height:18px;font-size:18px;flex:0 0 auto;color:var(--md-sys-color-primary)}.suggestion-label{min-width:0;font-size:13px;font-weight:700;line-height:1.35;overflow-wrap:anywhere}.suggestion-group{padding:2px 6px;border-radius:999px;background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface-variant);font-size:10px;font-weight:700;line-height:1.2}.suggestion-desc{font-size:12px;line-height:1.35;color:var(--md-sys-color-on-surface-variant);overflow-wrap:anywhere}.suggestion-actions{display:inline-flex;align-items:center;justify-content:flex-end;gap:4px}.suggestion-arrow{width:32px;height:32px;display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;color:var(--md-sys-color-on-surface-variant)}.suggestion-action-btn{color:var(--md-sys-color-on-surface-variant)}.suggestion-action-btn--danger,.history-session-tool--danger{color:var(--md-sys-color-error)}.suggestions-content .suggestion-item:hover,.suggestions-content .suggestion-item:focus-visible{border-color:color-mix(in srgb,var(--md-sys-color-primary) 58%,var(--md-sys-color-outline-variant));box-shadow:0 8px 18px color-mix(in srgb,var(--md-sys-color-primary) 18%,transparent),inset 0 0 0 1px color-mix(in srgb,var(--md-sys-color-primary) 28%,transparent);transform:translateY(-2px) scale(1.01)}.assistant-footer{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:8px;padding:10px 16px;border-top-color:color-mix(in srgb,var(--md-sys-color-primary) 20%,var(--md-sys-color-outline-variant));background:linear-gradient(180deg,color-mix(in srgb,var(--md-sys-color-primary-container) 16%,transparent),transparent 56%),var(--md-sys-color-surface-container-low)}.assistant-footer .task-footer{grid-column:1/-1}.composer-leading{color:var(--md-sys-color-primary)}.assistant-footer input{box-sizing:border-box;width:100%;min-width:0;height:34px;border:1px solid;border-radius:8px;padding:0 12px;color:var(--md-sys-color-on-surface);border-color:color-mix(in srgb,var(--md-sys-color-primary) 24%,var(--md-sys-color-outline-variant));background:var(--md-sys-color-surface);box-shadow:inset 0 1px 2px color-mix(in srgb,var(--md-sys-color-shadow, var(--md-sys-color-on-surface)) 12%,transparent)}.send-actions{min-width:36px;display:inline-flex;align-items:center;justify-content:center}.assistant-footer .send-btn{--praxis-icon-button-filled-background: var(--md-sys-color-primary);--praxis-icon-button-filled-foreground: var(--md-sys-color-on-primary)}.assistant-footer .send-btn.ready{color:var(--praxis-icon-button-filled-foreground)}.task-primary-btn{border-radius:12px;box-shadow:0 8px 18px color-mix(in srgb,var(--md-sys-color-primary) 24%,transparent)}@media(max-width:959px){.assistant-header{padding:12px 12px 10px}.assistant-section,.assistant-card{margin:4px 12px 10px}.assistant-header:after{left:12px;right:12px}.assistant-header .assistant-title{font-size:14px}.assistant-header .assistant-subtitle{font-size:10px}.assistant-footer{grid-template-columns:minmax(0,1fr) auto}.composer-leading{display:none}}.assistant-thought{margin-top:0;gap:10px;border-color:color-mix(in srgb,var(--md-sys-color-primary) 26%,var(--md-sys-color-outline-variant));background:linear-gradient(145deg,color-mix(in srgb,var(--md-sys-color-primary-container) 28%,transparent),transparent 58%),var(--md-sys-color-surface-container-low)}.assistant-thought-meta{display:inline-flex;align-items:center;gap:6px;font-size:11px;color:var(--md-sys-color-on-surface-variant)}.assistant-thought-meta mat-icon{width:15px;height:15px;font-size:15px;color:var(--md-sys-color-primary)}.assistant-thought-summary{font-size:13px;line-height:1.45;color:var(--md-sys-color-on-surface)}.assistant-thought-plan{border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 32%,var(--md-sys-color-outline-variant));border-radius:12px;padding:10px;background:var(--md-sys-color-surface-container-lowest);display:flex;flex-direction:column;gap:8px}.assistant-thought-plan-title{font-size:13px;font-weight:700;color:var(--md-sys-color-on-surface)}.assistant-thought-plan-actions{display:grid;grid-template-columns:repeat(auto-fit,minmax(0,1fr));gap:8px}.assistant-thought-plan-actions .mdc-button{min-width:0}.assistant-thought-plan-hint{font-size:11px;color:var(--md-sys-color-on-surface-variant);line-height:1.35}.assistant-thought-checklist{display:flex;flex-direction:column;gap:5px}.assistant-thought-checklist-item{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--md-sys-color-on-surface-variant)}.assistant-thought-checklist-item mat-icon{width:14px;height:14px;font-size:14px}.assistant-thought-shimmer{display:flex;flex-direction:column;gap:8px;margin-top:4px}.assistant-thought-shimmer .shimmer-line{height:12px;border-radius:4px;position:relative;overflow:hidden;background:var(--md-sys-color-surface-container-highest)}.assistant-thought-shimmer .shimmer-line:after{content:\"\";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--md-sys-color-primary) 8%,transparent),transparent);animation:assistantShimmerEffect 1.5s infinite}.assistant-thought-shimmer .shimmer-line-1{width:85%}.assistant-thought-shimmer .shimmer-line-2{width:92%}.assistant-thought-shimmer .shimmer-line-3{width:64%}@keyframes assistantShimmerEffect{to{transform:translate(100%)}}.assistant-flow{grid-template-columns:1fr;gap:6px}.flow-step{display:flex;align-items:flex-start;gap:8px;text-align:left;padding:7px 8px;border-radius:10px}.flow-step-index{width:18px;height:18px;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;font-size:10px;font-weight:700;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-highest);color:var(--md-sys-color-on-surface);flex:0 0 auto}.flow-step-content{min-width:0;display:flex;flex-direction:column;gap:1px}.flow-step-label{font-size:11px;font-weight:700;color:var(--md-sys-color-on-surface)}.flow-step-detail{font-size:11px;color:var(--md-sys-color-on-surface-variant);line-height:1.3}.flow-step.active .flow-step-index{border-color:color-mix(in srgb,var(--md-sys-color-primary) 60%,var(--md-sys-color-outline-variant));background:color-mix(in srgb,var(--md-sys-color-primary-container) 85%,var(--md-sys-color-surface-container-highest));color:var(--md-sys-color-on-primary-container)}.flow-step.done .flow-step-index{border-color:transparent;background:color-mix(in srgb,var(--md-sys-color-primary) 18%,var(--md-sys-color-surface-container-highest))}.task-timeline{margin-top:4px;display:grid;gap:6px}.task-timeline-item{display:flex;align-items:flex-start;gap:8px;border:1px solid var(--md-sys-color-outline-variant);border-radius:10px;padding:6px 8px;background:var(--md-sys-color-surface-container-low);opacity:.76}.task-timeline-item.active{opacity:1;border-color:color-mix(in srgb,var(--md-sys-color-primary) 40%,var(--md-sys-color-outline-variant));background:color-mix(in srgb,var(--md-sys-color-primary-container) 34%,var(--md-sys-color-surface-container-low))}.task-timeline-item.done{opacity:.9;border-color:color-mix(in srgb,var(--md-sys-color-primary) 24%,var(--md-sys-color-outline-variant))}.task-timeline-dot{width:18px;height:18px;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;font-size:10px;font-weight:700;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-highest);color:var(--md-sys-color-on-surface);flex:0 0 auto}.task-timeline-copy{min-width:0;display:flex;flex-direction:column;gap:1px}.task-timeline-title{font-size:11px;font-weight:700;color:var(--md-sys-color-on-surface)}.task-timeline-detail{font-size:11px;line-height:1.3;color:var(--md-sys-color-on-surface-variant)}.clarification-decision-head{display:inline-flex;align-items:center;width:100%;gap:6px;padding:8px 12px 0;box-sizing:border-box}.clarification-decision-index{width:18px;height:18px;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;font-size:10px;font-weight:700;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 35%,var(--md-sys-color-outline-variant));color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary-container) 68%,transparent)}.clarification-decision-type{font-size:10px;letter-spacing:.08em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant);opacity:.92}.clarification-decision-state{font-size:10px;font-weight:700;color:var(--md-sys-color-primary)}.clarification-option{border-color:color-mix(in srgb,var(--md-sys-color-primary) 20%,var(--md-sys-color-outline-variant));background:linear-gradient(145deg,color-mix(in srgb,var(--md-sys-color-primary-container) 16%,transparent),transparent 55%),var(--md-sys-color-surface-container-low)}.clarification-option.selected{border-color:color-mix(in srgb,var(--md-sys-color-primary) 56%,var(--md-sys-color-outline-variant));background:linear-gradient(145deg,color-mix(in srgb,var(--md-sys-color-primary-container) 44%,transparent),transparent 62%),var(--md-sys-color-surface-container);box-shadow:0 8px 16px color-mix(in srgb,var(--md-sys-color-primary) 18%,transparent)}.clarification-options-block{overflow:visible;padding-right:4px}@media(max-width:959px){.assistant-thought-plan-actions{grid-template-columns:1fr}}.ai-assistant-panel{width:min(604px,100vw - 18px)}.assistant-section,.assistant-card{margin:0;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 20%,var(--md-sys-color-outline-variant))}.assistant-section{min-height:0;padding:14px 16px;overflow:visible}.assistant-card{min-height:0;padding:14px 16px 16px;overflow:visible}.suggestions-area,.assistant-history,.loading-suggestions{overflow-y:auto;overflow-x:hidden}.section-header{min-width:0;display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:10px}.section-title{min-width:0;font-size:14px;font-weight:700;line-height:1.35;overflow-wrap:anywhere}.suggestions-actions{flex:0 0 auto;display:inline-flex;align-items:center}.review-area,.error-area,.success-area,.clarification-area{padding:0;overflow-y:auto;overflow-x:hidden;scrollbar-gutter:auto}.review-trust{margin:2px 0 4px}.trust-chip{max-width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.warnings-area,.review-summary,.review-diff,.apply-details,.clarification-options-block,.clarification-manual-toggle{width:100%;max-width:100%;min-width:0}.review-diff{padding:12px 14px}.review-diff-full{padding:10px;overflow-x:auto}.review-diff-block{min-width:0}.review-diff-block pre{overflow-wrap:anywhere;word-break:break-word}.clarification-options-block{padding:4px 2px 10px}.clarification-option{line-height:normal}:host ::ng-deep .clarification-option .mdc-button__label{line-height:1.35!important}.clarification-plain-label{padding:6px 12px 12px;font-size:14px;line-height:1.35}.clarification-manual-toggle{margin-top:10px;padding:10px 2px 0;flex-wrap:wrap;row-gap:6px}.suggestions-content .suggestion-actions{gap:6px}.suggestions-content .suggestion-arrow,.suggestions-content .suggestion-action-btn mat-icon,.suggestions-content .suggestion-arrow mat-icon{display:inline-flex;align-items:center;justify-content:center}:host ::ng-deep .assistant-quick-menu-panel{min-width:244px;max-width:min(90vw,320px);border-radius:14px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 26%,var(--md-sys-color-outline-variant));background:var(--md-sys-color-surface-container-high);box-shadow:0 12px 28px color-mix(in srgb,var(--md-sys-color-shadow, var(--md-sys-color-on-surface)) 32%,transparent),inset 0 1px color-mix(in srgb,var(--md-sys-color-on-surface) 6%,transparent);overflow:hidden;padding:6px}:host ::ng-deep .assistant-quick-menu-panel .mat-mdc-menu-item{min-height:36px;border-radius:10px;color:var(--md-sys-color-on-surface);font-size:12px;font-weight:500;margin:1px 0}:host ::ng-deep .assistant-quick-menu-panel .mat-mdc-menu-item .mat-icon{color:color-mix(in srgb,var(--md-sys-color-on-surface) 82%,var(--md-sys-color-on-surface-variant))}:host ::ng-deep .assistant-quick-menu-panel .mat-mdc-menu-item:hover:not([disabled]){background:color-mix(in srgb,var(--md-sys-color-primary-container) 45%,transparent)}:host ::ng-deep .assistant-quick-menu-panel .mat-mdc-menu-item:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:-2px}:host ::ng-deep .assistant-quick-menu-panel .assistant-quick-menu-danger{color:var(--md-sys-color-error)}:host ::ng-deep .assistant-quick-menu-panel .assistant-quick-menu-danger .mat-icon{color:var(--md-sys-color-error)}@media(max-width:959px){::ng-deep .ai-assistant-overlay-pane{top:12px!important;left:12px!important;width:calc(100vw - 24px)!important;height:calc(100vh - 24px)!important;max-width:calc(100vw - 24px);max-height:calc(100vh - 24px);transform:none!important}.ai-assistant-panel{width:calc(100vw - 48px);min-height:min(620px,100vh - 48px);max-height:calc(100vh - 48px)}.assistant-section,.assistant-card{margin:0}.assistant-card,.assistant-section{padding:12px}}.ai-trigger-btn{color:var(--md-sys-color-primary);opacity:1}.assistant-tab:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.assistant-close-btn{color:var(--md-sys-color-on-surface-variant)}.assistant-body{padding:12px 16px;overflow:hidden;min-height:0;flex:1;display:flex;flex-direction:column;gap:12px}.assistant-body>*{min-height:0}@media(max-width:959px){.assistant-nav{padding:8px 12px 0}.assistant-body,.assistant-footer{padding:10px 12px}.suggestions-content .suggestion-item{grid-template-columns:1fr;align-items:start}.suggestion-actions{justify-content:flex-start}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.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: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i4.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation", "cdkConnectedOverlayUsePopover", "cdkConnectedOverlayMatchWidth", "cdkConnectedOverlay"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: i4.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "ngmodule", type: A11yModule }, { kind: "directive", type: i5.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i7.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i8.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i15.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["role", "id", "aria-label", "aria-description", "value", "color", "removable", "highlighted", "disableRipple", "disabled"], outputs: ["removed", "destroyed"], exportAs: ["matChip"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i10.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i10.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i10.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }, { kind: "pipe", type: DatePipe, name: "date" }, { kind: "pipe", type: JsonPipe, name: "json" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
7743
7985
|
}
|
|
7744
7986
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisAiAssistantComponent, decorators: [{
|
|
7745
7987
|
type: Component,
|
|
@@ -7757,7 +7999,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
7757
7999
|
DatePipe,
|
|
7758
8000
|
JsonPipe,
|
|
7759
8001
|
NgTemplateOutlet,
|
|
7760
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- Trigger Button -->\n<button\n mat-icon-button\n cdkOverlayOrigin\n #trigger=\"cdkOverlayOrigin\"\n #triggerBtn\n (click)=\"open()\"\n [disabled]=\"isOpen\"\n class=\"ai-trigger-btn\"\n matTooltip=\"Assistente de Configura\u00E7\u00E3o\"\n aria-label=\"Abrir Assistente IA\">\n <mat-icon>auto_awesome</mat-icon>\n</button>\n\n<!-- Overlay Template -->\n<ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"trigger\"\n [cdkConnectedOverlayOpen]=\"isOpen\"\n [cdkConnectedOverlayHasBackdrop]=\"hasBackdrop\"\n [cdkConnectedOverlayPositions]=\"overlayPositions\"\n [cdkConnectedOverlayPush]=\"true\"\n [cdkConnectedOverlayViewportMargin]=\"12\"\n cdkConnectedOverlayPanelClass=\"ai-assistant-overlay-pane\"\n cdkConnectedOverlayBackdropClass=\"ai-assistant-backdrop\"\n (backdropClick)=\"close()\"\n (overlayOutsideClick)=\"close()\"\n (detach)=\"close()\">\n\n <div\n class=\"ai-assistant-panel\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"Assistente de Configura\u00E7\u00E3o\"\n [attr.aria-busy]=\"isBusyState() ? 'true' : null\"\n [cdkTrapFocus]=\"hasBackdrop\"\n [cdkTrapFocusAutoCapture]=\"hasBackdrop\"\n (keydown)=\"onKeydown($event)\"\n >\n\n <!-- HEADER -->\n <div class=\"assistant-header\">\n <div class=\"assistant-header__left\">\n <mat-icon class=\"magic-icon\">auto_awesome</mat-icon>\n <div class=\"assistant-title-group\">\n <div class=\"assistant-title\">Assistente de Configura\u00E7\u00E3o</div>\n <div class=\"assistant-subtitle\">Copiloto contextual para ajustes guiados</div>\n <div class=\"assistant-header-chips\">\n <span\n class=\"mode-chip\"\n [class.mock]=\"mockMode\"\n [matTooltip]=\"mockMode ? 'Sem chave de API: respostas de demonstra\u00E7\u00E3o' : 'Conectado ao assistente configurado'\"\n >\n {{ mockMode ? 'Mock' : 'Conectado' }}\n </span>\n <span\n class=\"policy-chip\"\n [class.strict]=\"isStrictRiskPolicy()\"\n [matTooltip]=\"getRiskPolicyTooltip()\"\n >\n {{ getRiskPolicyLabel() }}\n </span>\n </div>\n </div>\n </div>\n <div class=\"assistant-header__right\">\n <button\n mat-icon-button\n type=\"button\"\n class=\"assistant-close-btn\"\n (click)=\"close()\"\n aria-label=\"Fechar assistente\"\n matTooltip=\"Fechar assistente\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </div>\n </div>\n <div\n class=\"assistant-status\"\n [class.processing]=\"isBusyState()\"\n [class.pending]=\"state === 'clarification'\"\n [class.warning]=\"state === 'error'\"\n [class.success]=\"state === 'review' || state === 'success'\"\n [class.compact]=\"!shouldShowSystemStatusDetail()\"\n role=\"status\"\n [attr.aria-live]=\"getSystemStatusAriaLive()\"\n aria-atomic=\"true\"\n >\n <span class=\"assistant-status-dot\" aria-hidden=\"true\"></span>\n <div class=\"assistant-status-content\">\n <div class=\"assistant-status-label\">\n <span class=\"assistant-status-label-prefix\">Status:</span>\n <span>{{ getSystemStatusLabel() }}</span>\n @if (shouldShowSnapshotFallbackBadge()) {\n <span class=\"assistant-status-mode\">Snapshot</span>\n }\n </div>\n @if (shouldShowSystemStatusDetail()) {\n <div class=\"assistant-status-detail\">{{ getSystemStatusDetail() }}</div>\n }\n </div>\n </div>\n @if (shouldShowTaskFlow()) {\n <div class=\"assistant-flow\" role=\"list\" aria-label=\"Fluxo da proposta\">\n @for (step of flowSteps; track step) {\n <div\n class=\"flow-step\"\n role=\"listitem\"\n [class.active]=\"getFlowStepState(step.step) === 'active'\"\n [class.done]=\"getFlowStepState(step.step) === 'done'\"\n >\n <span class=\"flow-step-index\">{{ step.step }}</span>\n <span class=\"flow-step-content\">\n <span class=\"flow-step-label\">{{ step.label }}</span>\n <span class=\"flow-step-detail\">{{ getFlowStepDetail(step.step) }}</span>\n </span>\n </div>\n }\n </div>\n }\n <div class=\"assistant-nav\">\n <div\n class=\"assistant-tabs\"\n role=\"tablist\"\n aria-label=\"Se\u00E7\u00F5es do assistente\"\n (keydown)=\"onTabsKeydown($event)\"\n >\n @if (isTaskMode()) {\n <button\n class=\"assistant-tab\"\n type=\"button\"\n id=\"assistant-tab-task\"\n role=\"tab\"\n aria-label=\"Proposta atual\"\n [attr.aria-selected]=\"isActiveTab('task')\"\n aria-controls=\"assistant-panel-task\"\n [attr.tabindex]=\"isActiveTab('task') ? 0 : -1\"\n [class.active]=\"isActiveTab('task')\"\n (click)=\"setActiveTab('task')\"\n >\n Proposta\n @if (hasPendingClarification() && !isActiveTab('task')) {\n <span class=\"assistant-tab-badge\">1</span>\n }\n </button>\n }\n <button\n class=\"assistant-tab\"\n type=\"button\"\n id=\"assistant-tab-chat\"\n role=\"tab\"\n aria-label=\"Hist\u00F3rico\"\n [attr.aria-selected]=\"isActiveTab('chat')\"\n aria-controls=\"assistant-panel-chat\"\n [attr.tabindex]=\"isActiveTab('chat') ? 0 : -1\"\n [class.active]=\"isActiveTab('chat')\"\n (click)=\"setActiveTab('chat')\"\n >\n Hist\u00F3rico\n </button>\n <button\n class=\"assistant-tab\"\n type=\"button\"\n id=\"assistant-tab-suggestions\"\n role=\"tab\"\n aria-label=\"Sugest\u00F5es de melhoria\"\n [attr.aria-selected]=\"isActiveTab('suggestions')\"\n aria-controls=\"assistant-panel-suggestions\"\n [attr.tabindex]=\"isActiveTab('suggestions') ? 0 : -1\"\n [class.active]=\"isActiveTab('suggestions')\"\n (click)=\"setActiveTab('suggestions')\"\n >\n Sugest\u00F5es\n </button>\n </div>\n </div>\n\n <!-- BODY: Dynamic Content based on State -->\n <div class=\"assistant-body\">\n @if (shouldShowThoughtCard()) {\n <div class=\"assistant-thought assistant-section\">\n <div class=\"assistant-thought-meta\">\n <mat-icon>psychology</mat-icon>\n <span>{{ getThoughtTimingLabel() }}</span>\n </div>\n <div class=\"assistant-thought-summary\">{{ getThoughtSummary() }}</div>\n <div class=\"assistant-thought-plan\">\n <div class=\"assistant-thought-plan-title\">{{ getThoughtPlanTitle() }}</div>\n <div class=\"assistant-thought-plan-actions\">\n <button\n mat-stroked-button\n type=\"button\"\n class=\"thought-action-details\"\n (click)=\"openThoughtDetails()\"\n [attr.aria-label]=\"getThoughtDetailsLabel()\"\n [matTooltip]=\"getThoughtDetailsTooltip()\"\n >\n {{ getThoughtDetailsLabel() }}\n </button>\n @if (shouldShowThoughtPreviewAction()) {\n <button\n mat-flat-button\n color=\"primary\"\n type=\"button\"\n class=\"thought-action-preview\"\n (click)=\"openThoughtPreview()\"\n [matTooltip]=\"getThoughtPreviewTooltip()\"\n >\n Pr\u00E9via\n </button>\n }\n </div>\n <div class=\"assistant-thought-plan-hint\">{{ getThoughtActionHint() }}</div>\n @if (getThoughtChecklist(); as thoughtChecklist) {\n @if (thoughtChecklist.length) {\n <div class=\"assistant-thought-checklist\">\n @for (item of thoughtChecklist; track item) {\n <div class=\"assistant-thought-checklist-item\">\n <mat-icon>radio_button_unchecked</mat-icon>\n <span>{{ item }}</span>\n </div>\n }\n </div>\n }\n @if (isBusyState() && !thoughtChecklist.length) {\n <div class=\"assistant-thought-shimmer\">\n <div class=\"shimmer-line shimmer-line-1\"></div>\n <div class=\"shimmer-line shimmer-line-2\"></div>\n <div class=\"shimmer-line shimmer-line-3\"></div>\n </div>\n }\n }\n </div>\n </div>\n }\n @if (processingInfoVisible) {\n <div class=\"processing-banner\">\n <mat-spinner diameter=\"16\"></mat-spinner>\n <span>{{ aiExplanation || 'Analisando solicita\u00E7\u00E3o e preparando proposta...' }}</span>\n <button mat-button type=\"button\" class=\"processing-retry\" (click)=\"retryProcessing()\">Tentar novamente</button>\n </div>\n }\n @if (historyContext && isActiveTab('chat')) {\n <div\n class=\"assistant-history assistant-section\"\n id=\"assistant-panel-chat\"\n role=\"tabpanel\"\n aria-labelledby=\"assistant-tab-chat\"\n >\n <div class=\"section-header\">\n <div class=\"section-heading\">\n <div class=\"section-title\">Hist\u00F3rico</div>\n <div class=\"section-subtitle\">Sess\u00F5es recentes, pedidos reaproveit\u00E1veis e desfazer r\u00E1pido.</div>\n </div>\n <div class=\"history-actions\" role=\"group\" aria-label=\"A\u00E7\u00F5es do hist\u00F3rico\">\n <button\n mat-stroked-button\n type=\"button\"\n class=\"history-action-btn\"\n (click)=\"historyExpanded = !historyExpanded\"\n [matTooltip]=\"historyExpanded ? 'Recolher hist\u00F3rico' : 'Expandir hist\u00F3rico'\"\n [attr.aria-label]=\"historyExpanded ? 'Recolher hist\u00F3rico' : 'Expandir hist\u00F3rico'\"\n [disabled]=\"!historyWarnings.length && !historySessions.length && !activeHistoryMessages.length\"\n >\n <mat-icon>{{ historyExpanded ? 'expand_less' : 'expand_more' }}</mat-icon>\n <span>{{ historyExpanded ? 'Recolher' : 'Expandir' }}</span>\n </button>\n <button\n mat-stroked-button\n type=\"button\"\n class=\"history-action-btn\"\n (click)=\"startNewSession()\"\n matTooltip=\"Nova conversa\"\n aria-label=\"Nova conversa\"\n [disabled]=\"isBusyState()\"\n >\n <mat-icon>add_comment</mat-icon>\n <span>Nova conversa</span>\n </button>\n <button\n mat-stroked-button\n type=\"button\"\n (click)=\"clearHistory()\"\n matTooltip=\"Limpar hist\u00F3rico local\"\n aria-label=\"Limpar hist\u00F3rico local\"\n class=\"history-action-btn history-action-btn--danger\"\n [disabled]=\"!historySessions.length\"\n >\n <mat-icon>delete_outline</mat-icon>\n <span>Limpar</span>\n </button>\n </div>\n </div>\n @if (historyUndoDeleteSession) {\n <div class=\"history-undo\">\n <span>Sess\u00E3o removida.</span>\n <button mat-button type=\"button\" (click)=\"undoRemoveHistorySession()\">\n Desfazer\n </button>\n </div>\n }\n @if (historyExpanded && historyWarnings.length) {\n <div class=\"history-warnings\">\n <mat-icon>info</mat-icon>\n <div class=\"history-warnings-list\">\n @for (warning of historyWarnings; track warning) {\n <div>{{ warning }}</div>\n }\n <div class=\"history-warnings-hint\">\n Configure headers via API_CONFIG_STORAGE_OPTIONS no host.\n </div>\n </div>\n </div>\n }\n @if (historyExpanded && historySessions.length) {\n <div class=\"history-sessions\">\n @for (session of historySessions; track session.id) {\n <div\n class=\"history-session\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"selectHistorySession(session.id)\"\n (keydown)=\"onHistorySessionCardKeydown($event, session.id)\"\n [class.active]=\"session.id === activeHistorySession?.id\"\n [matTooltip]=\"getHistorySessionTooltip(session)\"\n [matTooltipDisabled]=\"!session.componentType && !session.componentId\"\n >\n <div class=\"history-session-main\">\n <span class=\"history-session-title\">{{ session.title }}</span>\n <div class=\"history-session-main-right\">\n <span class=\"history-session-time\">{{ session.updatedAt | date:'short' }}</span>\n <div class=\"history-session-tools\">\n <button\n mat-icon-button\n type=\"button\"\n class=\"history-session-tool\"\n (click)=\"reuseHistorySessionPrompt(session.id, $event)\"\n matTooltip=\"Reusar \u00FAltimo pedido\"\n aria-label=\"Reusar \u00FAltimo pedido\"\n >\n <mat-icon>edit_note</mat-icon>\n </button>\n <button\n mat-icon-button\n type=\"button\"\n class=\"history-session-tool history-session-tool--danger\"\n (click)=\"removeHistorySession(session.id, $event)\"\n matTooltip=\"Excluir sess\u00E3o\"\n aria-label=\"Excluir sess\u00E3o\"\n >\n <mat-icon>delete_outline</mat-icon>\n </button>\n </div>\n </div>\n </div>\n <div class=\"history-session-meta\">\n @if (session.componentType) {\n <span class=\"history-chip\">{{ session.componentType }}</span>\n }\n @if (session.componentId) {\n <span class=\"history-chip\">{{ session.componentId }}</span>\n }\n </div>\n </div>\n }\n </div>\n }\n @if (historyExpanded && !historySessions.length) {\n <div class=\"history-empty\">\n Nenhuma sess\u00E3o salva ainda.\n </div>\n }\n @if (historyExpanded && activeHistoryMessages.length) {\n <div class=\"history-messages\">\n @if (activeHistoryTotalMessages > activeHistoryMessages.length) {\n <div\n class=\"history-messages-hint\"\n >\n Mostrando \u00FAltimas {{ activeHistoryMessages.length }} de {{ activeHistoryTotalMessages }} mensagens.\n </div>\n }\n @for (msg of activeHistoryMessages; track msg.id) {\n <div\n class=\"history-message\"\n [class.user]=\"msg.role === 'user'\"\n [class.assistant]=\"msg.role === 'assistant'\"\n >\n <div class=\"history-message-header\">\n <span class=\"history-message-role\">{{ msg.role === 'user' ? 'Voc\u00EA' : 'Assistente' }}</span>\n <span class=\"history-message-time\">{{ msg.createdAt | date:'shortTime' }}</span>\n @if (msg.context?.usedRag) {\n <span\n class=\"history-rag\"\n matTooltip=\"Resposta baseada em contexto recuperado (RAG)\"\n >RAG</span>\n }\n </div>\n <div class=\"history-message-text\">{{ msg.text }}</div>\n </div>\n }\n </div>\n }\n @if (historyExpanded && historySessions.length && !activeHistoryMessages.length) {\n <div class=\"history-empty history-empty--panel\">\n Selecione uma sess\u00E3o para visualizar as mensagens.\n </div>\n }\n @if (historyExpanded) {\n <div class=\"history-helper\">\n O hist\u00F3rico \u00E9 local ao usu\u00E1rio e ao componente atual.\n </div>\n }\n </div>\n }\n\n @if (loadingSuggestions && isActiveTab('suggestions')) {\n <div\n class=\"loading-suggestions assistant-section\"\n id=\"assistant-panel-suggestions\"\n role=\"tabpanel\"\n aria-labelledby=\"assistant-tab-suggestions\"\n >\n <mat-spinner diameter=\"20\"></mat-spinner>\n <span>Carregando sugest\u00F5es de melhoria...</span>\n </div>\n }\n\n <!-- STATE: LISTENING (Suggestions) -->\n @if (state === 'listening' && isActiveTab('suggestions')) {\n <div\n class=\"suggestions-area assistant-section\"\n id=\"assistant-panel-suggestions\"\n role=\"tabpanel\"\n aria-labelledby=\"assistant-tab-suggestions\"\n >\n <div class=\"section-header\">\n <div class=\"section-title\">Sugest\u00F5es de melhoria</div>\n <div class=\"suggestions-actions\">\n <button mat-icon-button type=\"button\" (click)=\"refreshSuggestions()\" [disabled]=\"loadingSuggestions\" matTooltip=\"Atualizar sugest\u00F5es\">\n <mat-icon>refresh</mat-icon>\n </button>\n </div>\n </div>\n @if (!loadingSuggestions) {\n <div class=\"suggestions-hero\">\n <div class=\"suggestions-hero__label\">Contexto ativo</div>\n <div class=\"suggestions-hero__title\">{{ adapter.componentName || 'Componente atual' }}</div>\n <div class=\"suggestions-hero__detail\">{{ getSystemStatusDetail() }}</div>\n </div>\n }\n @if (suggestionsWarnings.length) {\n <div class=\"warnings-area\">\n <mat-icon class=\"warnings-icon\">warning_amber</mat-icon>\n <div class=\"warnings-content\">\n <div class=\"warnings-title\">Avisos</div>\n <div class=\"warnings-list\">\n @for (warning of suggestionsWarnings; track warning) {\n <div>{{ warning }}</div>\n }\n </div>\n </div>\n </div>\n }\n @if (!loadingSuggestions && (richSuggestions.length || hasDismissedSuggestions())) {\n <div class=\"suggestions-content\">\n @if (hasDismissedSuggestions()) {\n <div class=\"suggestions-filter\">\n <span>{{ getDismissedSuggestionCount() }} oculta(s)</span>\n <button mat-button type=\"button\" (click)=\"restoreDismissedSuggestions()\">\n Restaurar\n </button>\n </div>\n }\n @if (getVisibleSuggestions().length) {\n <div class=\"suggestions-list\">\n @for (sug of getVisibleSuggestions(); track sug.id) {\n <div\n class=\"suggestion-item\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'Selecionar sugest\u00E3o: ' + sug.label\"\n (click)=\"selectSuggestion(sug)\"\n (keydown)=\"onSuggestionCardKeydown($event, sug)\"\n >\n <div class=\"suggestion-copy\">\n <div class=\"suggestion-main\">\n @if (sug.icon) {\n <mat-icon class=\"suggestion-icon\">{{ sug.icon }}</mat-icon>\n }\n <span class=\"suggestion-label\">{{ sug.label }}</span>\n @if (sug.group) {\n <span class=\"suggestion-group\">{{ sug.group }}</span>\n }\n </div>\n @if (sug.description) {\n <div class=\"suggestion-desc\">{{ sug.description }}</div>\n }\n </div>\n <div class=\"suggestion-actions\">\n <span class=\"suggestion-arrow\" aria-hidden=\"true\">\n <mat-icon>chevron_right</mat-icon>\n </span>\n <button\n mat-icon-button\n type=\"button\"\n class=\"suggestion-action-btn\"\n (click)=\"prepareSuggestionPrompt(sug, $event)\"\n matTooltip=\"Refinar pedido\"\n aria-label=\"Refinar pedido\"\n >\n <mat-icon>edit</mat-icon>\n </button>\n <button\n mat-icon-button\n type=\"button\"\n class=\"suggestion-action-btn suggestion-action-btn--danger\"\n (click)=\"dismissSuggestion(sug, $event)\"\n matTooltip=\"Ocultar sugest\u00E3o\"\n aria-label=\"Ocultar sugest\u00E3o\"\n >\n <mat-icon>visibility_off</mat-icon>\n </button>\n </div>\n </div>\n }\n </div>\n } @else {\n <div class=\"suggestions-empty suggestions-empty--inline\">\n Todas as sugest\u00F5es foram ocultadas.\n </div>\n }\n </div>\n }\n @if (!loadingSuggestions && !richSuggestions.length) {\n <div class=\"suggestions-empty\">\n Nenhuma sugest\u00E3o dispon\u00EDvel no momento.\n </div>\n }\n @if (!loadingSuggestions && !richSuggestions.length) {\n <div class=\"suggestions-helper\">\n Selecione uma sugest\u00E3o acima ou descreva uma altera\u00E7\u00E3o no campo inferior.\n </div>\n }\n </div>\n }\n\n <!-- STATE: CLARIFICATION (Two-Step Flow) -->\n @if (state === 'clarification' && isActiveTab('task')) {\n <div\n class=\"clarification-area assistant-card\"\n id=\"assistant-panel-task\"\n role=\"tabpanel\"\n aria-labelledby=\"assistant-tab-task\"\n >\n @if (!shouldShowThoughtCard()) {\n <div class=\"task-header\">\n <div class=\"task-title\">{{ getTaskTitle() }}</div>\n <div class=\"task-subtitle\">{{ getTaskSubtitle() }}</div>\n @if (clarificationOptions.length > 1 && getTaskSelectionSummary(); as selectionSummary) {\n <div class=\"task-meta\">\n <span class=\"task-meta-label\">Selecionado:</span>\n <span class=\"task-meta-value\">{{ selectionSummary }}</span>\n </div>\n }\n @if (shouldShowTaskSteps()) {\n <div class=\"task-steps\">\n <span class=\"task-step active\">1 Dados</span>\n <span class=\"task-step\">2 Layout</span>\n <span class=\"task-step\">3 Revis\u00E3o</span>\n </div>\n }\n </div>\n }\n @if (clarificationResponseType === 'context') {\n <div class=\"context-only\">\n <mat-spinner diameter=\"24\"></mat-spinner>\n <div class=\"context-only-hint\">Buscando contexto adicional...</div>\n </div>\n }\n <ng-template #clarificationOptionContent let-opt let-index=\"index\" let-compact=\"compact\">\n @if (!compact) {\n <div class=\"clarification-decision-head\">\n <span class=\"clarification-decision-index\">{{ index + 1 }}</span>\n <span class=\"clarification-decision-type\">{{ getClarificationOptionKindLabel(opt) }}</span>\n <span class=\"spacer\"></span>\n @if (isClarificationSelected(opt)) {\n <span class=\"clarification-decision-state\">Selecionado</span>\n }\n </div>\n }\n @switch (getClarificationOptionLayout(opt)) {\n @case ('endpoint') {\n <div class=\"clarification-card\">\n <div class=\"clarification-card-header\">\n <mat-icon class=\"endpoint-icon\">{{ getEndpointIcon(opt) }}</mat-icon>\n @if (getEndpointMethod(opt); as method) {\n <span class=\"endpoint-method\" [attr.data-method]=\"method\">{{ method }}</span>\n }\n <span class=\"endpoint-label\">{{ opt.label }}</span>\n <span class=\"spacer\"></span>\n <mat-icon class=\"select-indicator\">\n {{ isClarificationSelected(opt) ? 'check_circle' : 'radio_button_unchecked' }}\n </mat-icon>\n </div>\n <div class=\"clarification-card-body\">\n @if (getEndpointPath(opt); as path) {\n <div class=\"endpoint-path\">{{ path }}</div>\n }\n @if (opt.contextHints?.description) {\n <div\n class=\"endpoint-description\"\n [matTooltip]=\"getDescriptionTooltip(opt)\"\n [matTooltipDisabled]=\"!shouldShowDescriptionTooltip(opt)\"\n >\n {{ opt.contextHints?.description }}\n </div>\n }\n </div>\n </div>\n }\n @case ('color') {\n <div class=\"clarification-color\">\n <span\n class=\"color-swatch\"\n [style.background]=\"getSafeHexColor(opt) || 'var(--md-sys-color-surface-container-highest)'\"\n ></span>\n <div class=\"color-meta\">\n <span class=\"color-label\">{{ opt.label }}</span>\n @if (opt.contextHints?.hexColor) {\n <span class=\"color-value\">{{ opt.contextHints?.hexColor }}</span>\n }\n </div>\n </div>\n }\n @case ('description') {\n <div class=\"clarification-description\">\n <span class=\"clarification-label\">{{ opt.label }}</span>\n @if (opt.contextHints?.description) {\n <span\n class=\"clarification-subtitle\"\n [matTooltip]=\"getDescriptionTooltip(opt)\"\n [matTooltipDisabled]=\"!shouldShowDescriptionTooltip(opt)\"\n >\n {{ opt.contextHints?.description }}\n </span>\n }\n </div>\n }\n @default {\n <span class=\"clarification-plain-label\">{{ opt.label }}</span>\n }\n }\n </ng-template>\n @if (warnings.length) {\n <div class=\"warnings-area\">\n <mat-icon class=\"warnings-icon\">warning_amber</mat-icon>\n <div class=\"warnings-content\">\n <div class=\"warnings-title\">Avisos</div>\n <div class=\"warnings-list\">\n @for (warning of warnings; track warning) {\n <div>{{ warning }}</div>\n }\n </div>\n </div>\n </div>\n }\n @if (clarificationQuestions.length) {\n <div\n class=\"clarification-questions\"\n [class.attention-highlight]=\"highlightClarificationDetails && !clarificationOptions.length\"\n >\n @for (question of clarificationQuestions; track question; let i = $index) {\n <div class=\"clarification-question\">\n <div class=\"clarification-question-label\">{{ question }}</div>\n <input\n type=\"text\"\n [(ngModel)]=\"clarificationAnswers[i]\"\n [placeholder]=\"'Resposta ' + (i + 1)\"\n autocomplete=\"off\">\n </div>\n }\n </div>\n }\n @if (clarificationOptions.length) {\n <div\n class=\"clarification-options-block\"\n [class.attention-highlight]=\"highlightClarificationDetails\"\n >\n <div class=\"clarification-options-title\">\n {{ clarificationOptions.length === 1 ? 'Decis\u00E3o sugerida' : 'Decis\u00F5es sugeridas' }}\n </div>\n @if (clarificationOptions.length === 1) {\n <div class=\"clarification-options-hint\">\n Etapa 2 de 4: confirme a melhor op\u00E7\u00E3o para continuar.\n </div>\n }\n @if (clarificationOptions.length > 1) {\n <div class=\"clarification-options-hint\">\n Etapa 2 de 4: selecione a alternativa mais aderente para gerar a proposta.\n </div>\n }\n @if (clarificationResponseType === 'confirm') {\n <div\n class=\"clarification-buttons\"\n [class.list]=\"clarificationPresentation === 'list'\"\n >\n @for (opt of clarificationOptions; track opt.value; let i = $index) {\n <button\n mat-button\n type=\"button\"\n (click)=\"onClarificationOptionClick(opt)\"\n class=\"clarification-option\"\n [class.selected]=\"isClarificationSelected(opt)\"\n [matTooltip]=\"getClarificationTooltip(opt)\"\n [matTooltipDisabled]=\"!shouldShowClarificationTooltip(opt) || isEndpointOption(opt)\"\n >\n <ng-container *ngTemplateOutlet=\"clarificationOptionContent; context: { $implicit: opt, index: i, compact: false }\"></ng-container>\n </button>\n }\n </div>\n }\n @if (clarificationSelectionMode === 'multiple') {\n <div\n class=\"clarification-buttons\"\n [class.list]=\"clarificationPresentation === 'list'\"\n >\n @for (opt of clarificationOptions; track opt.value; let i = $index) {\n <button\n mat-button\n type=\"button\"\n (click)=\"onClarificationOptionClick(opt)\"\n [class.selected]=\"isClarificationSelected(opt)\"\n class=\"clarification-option\"\n [matTooltip]=\"getClarificationTooltip(opt)\"\n [matTooltipDisabled]=\"!shouldShowClarificationTooltip(opt) || isEndpointOption(opt)\"\n >\n <ng-container *ngTemplateOutlet=\"clarificationOptionContent; context: { $implicit: opt, index: i, compact: false }\"></ng-container>\n </button>\n }\n </div>\n }\n @if (clarificationResponseType !== 'confirm' && clarificationSelectionMode === 'single' && clarificationPresentation !== 'chips') {\n <div\n class=\"clarification-buttons\"\n [class.list]=\"clarificationPresentation === 'list'\"\n >\n @for (opt of clarificationOptions; track opt.value; let i = $index) {\n <button\n mat-button\n type=\"button\"\n (click)=\"onClarificationOptionClick(opt)\"\n class=\"clarification-option\"\n [class.selected]=\"isClarificationSelected(opt)\"\n [matTooltip]=\"getClarificationTooltip(opt)\"\n [matTooltipDisabled]=\"!shouldShowClarificationTooltip(opt) || isEndpointOption(opt)\"\n >\n <ng-container *ngTemplateOutlet=\"clarificationOptionContent; context: { $implicit: opt, index: i, compact: false }\"></ng-container>\n </button>\n }\n </div>\n }\n @if (clarificationResponseType !== 'confirm' && clarificationSelectionMode === 'single' && clarificationPresentation === 'chips') {\n <div\n class=\"clarification-chips\"\n >\n @for (opt of clarificationOptions; track opt.value; let i = $index) {\n @if (isEndpointOption(opt)) {\n <button\n mat-button\n type=\"button\"\n class=\"clarification-option clarification-card-button\"\n (click)=\"onClarificationOptionClick(opt)\"\n [class.selected]=\"isClarificationSelected(opt)\"\n [matTooltip]=\"getClarificationTooltip(opt)\"\n [matTooltipDisabled]=\"!shouldShowClarificationTooltip(opt) || isEndpointOption(opt)\"\n >\n <ng-container *ngTemplateOutlet=\"clarificationOptionContent; context: { $implicit: opt, index: i, compact: false }\"></ng-container>\n </button>\n } @else {\n <mat-chip\n (click)=\"onClarificationOptionClick(opt)\"\n [matTooltip]=\"getClarificationTooltip(opt)\"\n [matTooltipDisabled]=\"!shouldShowClarificationTooltip(opt)\"\n class=\"clarification-chip\"\n >\n <ng-container *ngTemplateOutlet=\"clarificationOptionContent; context: { $implicit: opt, index: i, compact: true }\"></ng-container>\n </mat-chip>\n }\n }\n </div>\n }\n </div>\n }\n @if (clarificationAllowCustom && clarificationResponseType !== 'context') {\n <div\n class=\"clarification-manual-toggle\"\n >\n <span class=\"clarification-manual-label\">N\u00E3o encontrou o recurso?</span>\n <button mat-button type=\"button\" (click)=\"toggleManualInput()\">\n {{ showManualInput ? 'Ocultar resposta manual' : 'Responder manualmente' }}\n </button>\n </div>\n }\n @if (clarificationAllowCustom && showManualInput && clarificationResponseType !== 'context') {\n <div\n class=\"clarification-free\"\n >\n <input\n type=\"text\"\n [(ngModel)]=\"clarificationFreeText\"\n placeholder=\"Digite sua resposta\u2026\"\n autocomplete=\"off\"\n (keydown.enter)=\"confirmTaskAction()\"\n />\n </div>\n }\n @if (clarificationAllowCustom && showManualInput && clarificationResponseType !== 'context') {\n <div\n class=\"clarification-free-hint\"\n >\n Pressione Enter para enviar.\n </div>\n }\n </div>\n }\n\n <!-- STATE: REVIEW (Diff/Explanation) -->\n @if (state === 'review' && isActiveTab('task')) {\n <div\n class=\"review-area assistant-card\"\n id=\"assistant-panel-task\"\n role=\"tabpanel\"\n aria-labelledby=\"assistant-tab-task\"\n >\n @if (!shouldShowThoughtCard()) {\n <div class=\"task-header\">\n <div class=\"task-title\">{{ getTaskTitle() }}</div>\n <div class=\"task-subtitle\">{{ getTaskSubtitle() }}</div>\n @if (clarificationOptions.length > 1 && getTaskSelectionSummary(); as selectionSummary) {\n <div class=\"task-meta\">\n <span class=\"task-meta-label\">Selecionado:</span>\n <span class=\"task-meta-value\">{{ selectionSummary }}</span>\n </div>\n }\n @if (shouldShowTaskSteps()) {\n <div class=\"task-steps\">\n <span class=\"task-step\">1 Dados</span>\n <span class=\"task-step\">2 Layout</span>\n <span class=\"task-step active\">3 Revis\u00E3o</span>\n </div>\n }\n </div>\n }\n @if (warnings.length) {\n <div class=\"warnings-area\">\n <mat-icon class=\"warnings-icon\">warning_amber</mat-icon>\n <div class=\"warnings-content\">\n <div class=\"warnings-title\">Avisos</div>\n <div class=\"warnings-list\">\n @for (warning of warnings; track warning) {\n <div>{{ warning }}</div>\n }\n </div>\n </div>\n </div>\n }\n <div class=\"review-trust\">\n <span class=\"trust-chip\" [matTooltip]=\"getScopeTooltip()\">{{ getScopeLabel() }}</span>\n <span class=\"trust-chip\" [matTooltip]=\"getConfidenceTooltip()\">{{ getConfidenceLabel() }}</span>\n <span class=\"trust-chip risk-chip\" [class.medium]=\"getReviewRiskLevel() === 'm\u00E9dio'\" [class.high]=\"getReviewRiskLevel() === 'alto'\">\n Risco {{ getReviewRiskLevel() }}\n </span>\n </div>\n <div class=\"review-summary\" [class.attention-highlight]=\"highlightReviewDetails\">\n <div class=\"review-summary-title\">Resumo da proposta</div>\n <div class=\"review-summary-line\">{{ getReviewSummary() }}</div>\n </div>\n <div class=\"review-diff\">\n <div class=\"review-diff-title\">Pr\u00E9via de mudan\u00E7as</div>\n @if (pendingDiff.length) {\n <div class=\"review-diff-summary\">\n @for (line of getDiffSummaryLines(); track line) {\n <div class=\"review-diff-line\">{{ line }}</div>\n }\n @if (pendingDiff.length > 3) {\n <div class=\"review-diff-more\">\u2026 +{{ pendingDiff.length - 3 }} mudan\u00E7as</div>\n }\n </div>\n <button mat-stroked-button type=\"button\" class=\"review-diff-toggle\" (click)=\"toggleFullDiff()\">\n {{ getDiffToggleLabel() }}\n </button>\n } @else {\n <div class=\"review-diff-empty\">\n N\u00E3o foi poss\u00EDvel gerar um diff estruturado. Revise o resumo e aplique com cautela.\n </div>\n }\n @if (showFullDiff && pendingDiff.length) {\n <div class=\"review-diff-full\">\n @for (diff of pendingDiff; track diff.path) {\n <div class=\"review-diff-block\">\n <div class=\"review-diff-path\">{{ diff.path }}</div>\n <div class=\"review-diff-label\">Antes:</div>\n <pre>{{ diff.before | json }}</pre>\n <div class=\"review-diff-label\">Depois:</div>\n <pre>{{ diff.after | json }}</pre>\n </div>\n }\n </div>\n }\n </div>\n @if (aiExplanation.trim()) {\n <div class=\"ai-explanation\">\n {{ aiExplanation }}\n </div>\n }\n </div>\n }\n\n <!-- STATE: ERROR -->\n @if (state === 'error' && (isActiveTab('task') || (!isTaskMode() && isActiveTab('suggestions')))) {\n <div\n class=\"error-area assistant-card\"\n [attr.id]=\"isTaskMode() ? 'assistant-panel-task' : 'assistant-panel-suggestions'\"\n role=\"tabpanel\"\n [attr.aria-labelledby]=\"isTaskMode() ? 'assistant-tab-task' : 'assistant-tab-suggestions'\"\n >\n <div class=\"error-msg\">\n <mat-icon color=\"warn\">error_outline</mat-icon>\n <span>{{ errorMsg }}</span>\n </div>\n @if (warnings.length) {\n <div class=\"warnings-area\">\n <mat-icon class=\"warnings-icon\">warning_amber</mat-icon>\n <div class=\"warnings-content\">\n <div class=\"warnings-title\">Avisos</div>\n <div class=\"warnings-list\">\n @for (warning of warnings; track warning) {\n <div>{{ warning }}</div>\n }\n </div>\n </div>\n </div>\n }\n @if (shouldShowApplyDetails()) {\n <div class=\"apply-details\">\n <div class=\"apply-details-header\">\n <div class=\"apply-details-title\">Detalhes da aplica\u00E7\u00E3o</div>\n @if (allowManualPatchEdit) {\n <div class=\"apply-details-actions\">\n <button mat-button type=\"button\" (click)=\"togglePatchPathEditor()\" [disabled]=\"!pendingPatch\">\n {{ patchPathEditorExpanded ? 'Ocultar paths' : 'Editar por path' }}\n </button>\n <button mat-button type=\"button\" (click)=\"togglePatchEditor()\" [disabled]=\"!pendingPatch\">\n {{ patchEditorExpanded ? 'Ocultar editor' : 'Editar patch' }}\n </button>\n </div>\n }\n </div>\n @if (lastApplyAt) {\n <div class=\"apply-details-meta\">\n \u00DAltima tentativa: {{ lastApplyAt | date:'short' }}\n </div>\n }\n @if (getApplyPaths().length) {\n <div class=\"apply-paths\">\n @for (path of getApplyPaths(); track path) {\n <span class=\"apply-path-chip\">{{ path }}</span>\n }\n </div>\n }\n @if (applyWarnings.length) {\n <div class=\"apply-warnings\">\n <div class=\"apply-warnings-title\">Avisos da aplica\u00E7\u00E3o</div>\n <div class=\"apply-warnings-list\">\n @for (warning of applyWarnings; track warning) {\n <div>{{ warning }}</div>\n }\n </div>\n </div>\n }\n @if (allowManualPatchEdit && patchPathEditorExpanded) {\n <div class=\"patch-path-editor\">\n <div class=\"patch-editor-label\">Editar por path</div>\n <div class=\"patch-editor-hint\">Texto simples vira string; para for\u00E7ar texto em true/false/n\u00FAmero, use aspas.</div>\n @if (!getEditablePatchPathEdits().length) {\n <div class=\"patch-path-editor-empty\">\n Nenhum path edit\u00E1vel dispon\u00EDvel para este patch.\n </div>\n }\n @if (getEditablePatchPathEdits().length) {\n <div class=\"patch-path-rows\">\n @for (edit of getEditablePatchPathEdits(); track edit.path; let i = $index) {\n <div class=\"patch-path-row\">\n <div class=\"patch-path-label\">{{ edit.path }}</div>\n <input\n type=\"text\"\n [(ngModel)]=\"patchPathEdits[i].valueText\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n />\n @if (patchPathEdits[i].error) {\n <div class=\"patch-editor-error\">{{ patchPathEdits[i].error }}</div>\n }\n </div>\n }\n </div>\n }\n @if (patchPathEditorError) {\n <div class=\"patch-editor-error\">{{ patchPathEditorError }}</div>\n }\n <div class=\"patch-editor-actions\">\n <button mat-button type=\"button\" (click)=\"resetPatchPathEdits()\">\n Restaurar valores\n </button>\n <button mat-button type=\"button\" (click)=\"applyPathEditsToPatch()\">\n Aplicar no patch\n </button>\n <button mat-flat-button color=\"primary\" type=\"button\" (click)=\"reapplyPathEdits()\">\n Reaplicar por path\n </button>\n </div>\n </div>\n }\n @if (allowManualPatchEdit && patchEditorExpanded) {\n <div class=\"patch-editor\">\n <label class=\"patch-editor-label\">Patch JSON</label>\n <textarea\n [(ngModel)]=\"patchEditorText\"\n spellcheck=\"false\"\n ></textarea>\n @if (patchEditorError) {\n <div class=\"patch-editor-error\">{{ patchEditorError }}</div>\n }\n <div class=\"patch-editor-actions\">\n <button mat-button type=\"button\" (click)=\"resetPatchEditor()\">\n Restaurar original\n </button>\n <button mat-flat-button color=\"primary\" type=\"button\" (click)=\"reapplyEditedPatch()\">\n Reaplicar patch\n </button>\n </div>\n </div>\n }\n </div>\n }\n <div class=\"review-actions\">\n <button mat-button (click)=\"close()\">Fechar</button>\n <button mat-stroked-button (click)=\"retry()\">Tentar Novamente</button>\n </div>\n </div>\n }\n\n <!-- STATE: SUCCESS -->\n @if (state === 'success' && (isActiveTab('task') || (!isTaskMode() && isActiveTab('suggestions')))) {\n <div\n class=\"success-area assistant-card\"\n [attr.id]=\"isTaskMode() ? 'assistant-panel-task' : 'assistant-panel-suggestions'\"\n role=\"tabpanel\"\n [attr.aria-labelledby]=\"isTaskMode() ? 'assistant-tab-task' : 'assistant-tab-suggestions'\"\n >\n <div class=\"success-msg\">\n <mat-icon class=\"success-icon\">check_circle</mat-icon>\n <span>{{ aiExplanation || 'Configura\u00E7\u00E3o atualizada.' }}</span>\n </div>\n @if (warnings.length) {\n <div class=\"warnings-area\">\n <mat-icon class=\"warnings-icon\">warning_amber</mat-icon>\n <div class=\"warnings-content\">\n <div class=\"warnings-title\">Avisos</div>\n <div class=\"warnings-list\">\n @for (warning of warnings; track warning) {\n <div>{{ warning }}</div>\n }\n </div>\n </div>\n </div>\n }\n @if (shouldShowApplyDetails()) {\n <div class=\"apply-details\">\n <div class=\"apply-details-header\">\n <div class=\"apply-details-title\">Detalhes da aplica\u00E7\u00E3o</div>\n @if (allowManualPatchEdit) {\n <div class=\"apply-details-actions\">\n <button mat-button type=\"button\" (click)=\"togglePatchPathEditor()\" [disabled]=\"!pendingPatch\">\n {{ patchPathEditorExpanded ? 'Ocultar paths' : 'Editar por path' }}\n </button>\n <button mat-button type=\"button\" (click)=\"togglePatchEditor()\" [disabled]=\"!pendingPatch\">\n {{ patchEditorExpanded ? 'Ocultar editor' : 'Editar e reaplicar' }}\n </button>\n </div>\n }\n </div>\n @if (lastApplyAt) {\n <div class=\"apply-details-meta\">\n Aplicado em {{ lastApplyAt | date:'short' }}\n </div>\n }\n @if (getApplyPaths().length) {\n <div class=\"apply-paths\">\n @for (path of getApplyPaths(); track path) {\n <span class=\"apply-path-chip\">{{ path }}</span>\n }\n </div>\n }\n @if (applyWarnings.length) {\n <div class=\"apply-warnings\">\n <div class=\"apply-warnings-title\">Avisos da aplica\u00E7\u00E3o</div>\n <div class=\"apply-warnings-list\">\n @for (warning of applyWarnings; track warning) {\n <div>{{ warning }}</div>\n }\n </div>\n </div>\n }\n @if (allowManualPatchEdit && patchPathEditorExpanded) {\n <div class=\"patch-path-editor\">\n <div class=\"patch-editor-label\">Editar por path</div>\n <div class=\"patch-editor-hint\">Texto simples vira string; para for\u00E7ar texto em true/false/n\u00FAmero, use aspas.</div>\n @if (!getEditablePatchPathEdits().length) {\n <div class=\"patch-path-editor-empty\">\n Nenhum path edit\u00E1vel dispon\u00EDvel para este patch.\n </div>\n }\n @if (getEditablePatchPathEdits().length) {\n <div class=\"patch-path-rows\">\n @for (edit of getEditablePatchPathEdits(); track edit.path; let i = $index) {\n <div class=\"patch-path-row\">\n <div class=\"patch-path-label\">{{ edit.path }}</div>\n <input\n type=\"text\"\n [(ngModel)]=\"patchPathEdits[i].valueText\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n />\n @if (patchPathEdits[i].error) {\n <div class=\"patch-editor-error\">{{ patchPathEdits[i].error }}</div>\n }\n </div>\n }\n </div>\n }\n @if (patchPathEditorError) {\n <div class=\"patch-editor-error\">{{ patchPathEditorError }}</div>\n }\n <div class=\"patch-editor-actions\">\n <button mat-button type=\"button\" (click)=\"resetPatchPathEdits()\">\n Restaurar valores\n </button>\n <button mat-button type=\"button\" (click)=\"applyPathEditsToPatch()\">\n Aplicar no patch\n </button>\n <button mat-flat-button color=\"primary\" type=\"button\" (click)=\"reapplyPathEdits()\">\n Reaplicar por path\n </button>\n </div>\n </div>\n }\n @if (allowManualPatchEdit && patchEditorExpanded) {\n <div class=\"patch-editor\">\n <label class=\"patch-editor-label\">Patch JSON</label>\n <textarea\n [(ngModel)]=\"patchEditorText\"\n spellcheck=\"false\"\n ></textarea>\n @if (patchEditorError) {\n <div class=\"patch-editor-error\">{{ patchEditorError }}</div>\n }\n <div class=\"patch-editor-actions\">\n <button mat-button type=\"button\" (click)=\"resetPatchEditor()\">\n Restaurar original\n </button>\n <button mat-flat-button color=\"primary\" type=\"button\" (click)=\"reapplyEditedPatch()\">\n Reaplicar patch\n </button>\n </div>\n </div>\n }\n </div>\n }\n <button mat-button color=\"warn\" (click)=\"undoLastChange()\">\n <mat-icon>undo</mat-icon> Desfazer\n </button>\n </div>\n }\n\n </div>\n\n <div class=\"assistant-footer\">\n @if (!isTaskMode()) {\n <button\n mat-icon-button\n type=\"button\"\n class=\"composer-leading composer-leading-btn\"\n [matMenuTriggerFor]=\"assistantQuickMenu\"\n aria-label=\"Abrir a\u00E7\u00F5es r\u00E1pidas\"\n matTooltip=\"A\u00E7\u00F5es r\u00E1pidas\"\n >\n <mat-icon>add</mat-icon>\n </button>\n <input\n #inputEl\n type=\"text\"\n [(ngModel)]=\"userPrompt\"\n [disabled]=\"state === 'processing' || state === 'applying'\"\n placeholder=\"Descreva a altera\u00E7\u00E3o que deseja aplicar\u2026\"\n autocomplete=\"off\"\n />\n <div class=\"send-actions\">\n @if (state === 'listening') {\n <button\n mat-icon-button\n class=\"send-btn\"\n (click)=\"submitPrompt()\"\n [disabled]=\"!userPrompt.trim()\"\n [class.ready]=\"!!userPrompt.trim()\"\n >\n <mat-icon>arrow_upward</mat-icon>\n </button>\n }\n @if (state === 'processing' || state === 'applying') {\n <mat-spinner diameter=\"20\"></mat-spinner>\n }\n </div>\n } @else {\n <div class=\"task-footer\">\n <div class=\"task-footer-left\">\n <button mat-button type=\"button\" (click)=\"handleTaskSecondary()\">{{ getTaskCancelLabel() }}</button>\n @if (state === 'review') {\n <button\n mat-stroked-button\n type=\"button\"\n (click)=\"retry()\"\n >\n {{ getTaskSecondaryLabel() }}\n </button>\n }\n </div>\n <div class=\"task-footer-right\">\n <button\n class=\"task-primary-btn\"\n mat-flat-button\n color=\"primary\"\n type=\"button\"\n (click)=\"confirmTaskAction()\"\n [disabled]=\"isTaskPrimaryDisabled()\"\n >\n {{ getTaskPrimaryLabel() }}\n </button>\n @if (state === 'processing' || state === 'applying') {\n <mat-spinner diameter=\"20\"></mat-spinner>\n }\n </div>\n </div>\n }\n </div>\n\n <mat-menu #assistantQuickMenu=\"matMenu\" panelClass=\"assistant-quick-menu-panel\">\n <button mat-menu-item type=\"button\" (click)=\"setActiveTab('chat')\">\n <mat-icon>history</mat-icon>\n <span>Hist\u00F3rico</span>\n </button>\n <button mat-menu-item type=\"button\" (click)=\"setActiveTab('suggestions')\">\n <mat-icon>lightbulb</mat-icon>\n <span>Sugest\u00F5es</span>\n </button>\n <button mat-menu-item type=\"button\" (click)=\"startNewSession()\">\n <mat-icon>add_comment</mat-icon>\n <span>Nova conversa</span>\n </button>\n <button mat-menu-item type=\"button\" (click)=\"refreshSuggestions()\" [disabled]=\"loadingSuggestions\">\n <mat-icon>refresh</mat-icon>\n <span>Atualizar sugest\u00F5es</span>\n </button>\n <button\n mat-menu-item\n type=\"button\"\n (click)=\"restoreDismissedSuggestions()\"\n [disabled]=\"!hasDismissedSuggestions()\"\n >\n <mat-icon>visibility</mat-icon>\n <span>Restaurar sugest\u00F5es ocultas</span>\n </button>\n <button\n mat-menu-item\n type=\"button\"\n class=\"assistant-quick-menu-danger\"\n (click)=\"clearHistory()\"\n [disabled]=\"!historySessions.length\"\n >\n <mat-icon>delete_outline</mat-icon>\n <span>Limpar hist\u00F3rico local</span>\n </button>\n </mat-menu>\n </div>\n\n</ng-template>\n", styles: ["@keyframes assistantPremiumEnter{0%{opacity:0;transform:translate(14px) scale(.99)}to{opacity:1;transform:translate(0) scale(1)}}:host ::ng-deep .ai-assistant-backdrop{background:color-mix(in srgb,var(--md-sys-color-scrim, var(--md-sys-color-shadow, var(--md-sys-color-on-surface))) 42%,transparent);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}::ng-deep .ai-assistant-overlay-pane{max-width:calc(100vw - 24px);max-height:calc(100vh - 24px)}.ai-assistant-panel{box-sizing:border-box;width:min(604px,100vw - 18px);min-height:min(620px,100vh - 18px);max-height:min(820px,100vh - 18px);display:flex;flex-direction:column;overflow:hidden;color:var(--md-sys-color-on-surface);border-left:1px solid color-mix(in srgb,var(--md-sys-color-primary) 24%,var(--md-sys-color-outline-variant));border-top:1px solid color-mix(in srgb,var(--md-sys-color-primary) 18%,var(--md-sys-color-outline-variant));border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-primary) 18%,var(--md-sys-color-outline-variant));box-shadow:0 18px 48px color-mix(in srgb,var(--md-sys-color-shadow, var(--md-sys-color-on-surface)) 42%,transparent),inset 0 1px color-mix(in srgb,var(--md-sys-color-on-surface) 10%,transparent);background:radial-gradient(circle at 14% 8%,color-mix(in srgb,var(--md-sys-color-primary-container) 38%,transparent) 0%,transparent 44%),linear-gradient(165deg,color-mix(in srgb,var(--md-sys-color-surface-container-highest) 88%,var(--md-sys-color-surface)),var(--md-sys-color-surface));animation:assistantPremiumEnter .24s cubic-bezier(.22,1,.36,1)}.assistant-header{position:relative;display:flex;align-items:flex-start;justify-content:space-between;gap:12px;padding:12px 16px 10px;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-primary) 18%,var(--md-sys-color-outline-variant));background:linear-gradient(130deg,color-mix(in srgb,var(--md-sys-color-primary-container) 28%,transparent) 0%,transparent 52%),var(--md-sys-color-surface-container-low)}.assistant-header:after{content:\"\";position:absolute;left:16px;right:16px;bottom:-1px;height:1px;background:linear-gradient(90deg,color-mix(in srgb,var(--md-sys-color-primary) 55%,transparent),transparent);pointer-events:none}.assistant-header .assistant-header__left{min-width:0;display:flex;align-items:flex-start;gap:12px}.assistant-header .magic-icon{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;width:30px;height:30px;font-size:18px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 30%,transparent);box-shadow:0 4px 12px color-mix(in srgb,var(--md-sys-color-primary) 26%,transparent)}.assistant-header .assistant-title-group{min-width:0;display:flex;flex-direction:column;gap:4px}.assistant-header .assistant-title{font-size:15px;font-weight:700;letter-spacing:.01em;overflow-wrap:anywhere}.assistant-header .assistant-subtitle{display:block;font-size:11px;line-height:1.25;color:color-mix(in srgb,var(--md-sys-color-on-surface) 70%,var(--md-sys-color-on-surface-variant));overflow-wrap:anywhere}.assistant-header-chips{display:inline-flex;align-items:center;flex-wrap:wrap;gap:6px}.assistant-header .mode-chip{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:999px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 28%,var(--md-sys-color-outline-variant));background:color-mix(in srgb,var(--md-sys-color-primary-container) 64%,var(--md-sys-color-surface-container));color:color-mix(in srgb,var(--md-sys-color-on-primary-container) 85%,var(--md-sys-color-on-surface));font-size:10px;font-weight:700;letter-spacing:.04em;text-transform:uppercase}.assistant-header .mode-chip:before{content:\"\";width:6px;height:6px;border-radius:999px;background:currentColor;box-shadow:0 0 0 3px color-mix(in srgb,currentColor 16%,transparent)}.assistant-header .mode-chip.mock{border-color:color-mix(in srgb,var(--md-sys-color-error) 34%,var(--md-sys-color-outline-variant));background:color-mix(in srgb,var(--md-sys-color-error-container) 72%,var(--md-sys-color-surface-container));color:color-mix(in srgb,var(--md-sys-color-on-error-container) 85%,var(--md-sys-color-error))}.assistant-header .policy-chip{padding:2px 8px;border-radius:999px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 84%,transparent);background:var(--md-sys-color-surface-container-high);font-size:10px;letter-spacing:.02em;font-weight:600}.assistant-header .policy-chip.strict{border-color:color-mix(in srgb,var(--md-sys-color-primary) 42%,var(--md-sys-color-outline-variant));background:color-mix(in srgb,var(--md-sys-color-primary-container) 56%,var(--md-sys-color-surface-container-high))}.assistant-status{display:flex;align-items:flex-start;gap:10px;padding:10px 16px;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-primary) 18%,var(--md-sys-color-outline-variant));border-radius:0;background:linear-gradient(160deg,color-mix(in srgb,var(--md-sys-color-primary-container) 24%,transparent),transparent 48%),var(--md-sys-color-surface-container-low)}.assistant-status-dot{width:8px;height:8px;margin-top:6px;border-radius:999px;flex:0 0 auto;background:var(--md-sys-color-primary);box-shadow:0 0 0 4px color-mix(in srgb,var(--md-sys-color-primary) 16%,transparent)}.assistant-status.warning .assistant-status-dot{background:var(--md-sys-color-error);box-shadow:0 0 0 4px color-mix(in srgb,var(--md-sys-color-error) 16%,transparent)}.assistant-status.success .assistant-status-dot{background:color-mix(in srgb,var(--md-sys-color-primary) 74%,var(--md-sys-color-tertiary, var(--md-sys-color-primary)))}.assistant-status-content{min-width:0;display:flex;flex-direction:column;gap:2px}.assistant-status-label{display:flex;align-items:center;flex-wrap:wrap;gap:4px;font-size:12px;font-weight:700;line-height:1.35}.assistant-status-detail{font-size:11px;line-height:1.4;color:var(--md-sys-color-on-surface-variant);overflow-wrap:anywhere}.assistant-status-mode{padding:1px 6px;border-radius:999px;background:color-mix(in srgb,var(--md-sys-color-primary-container) 72%,transparent);color:var(--md-sys-color-on-primary-container);font-size:10px;font-weight:700}.assistant-nav{padding:8px 16px 0}.assistant-nav .assistant-tabs{display:flex;align-items:center;gap:4px;border-radius:12px;padding:5px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 24%,var(--md-sys-color-outline-variant));border-color:color-mix(in srgb,var(--md-sys-color-primary) 24%,var(--md-sys-color-outline-variant));background:linear-gradient(155deg,color-mix(in srgb,var(--md-sys-color-primary-container) 14%,transparent),transparent 58%),var(--md-sys-color-surface-container-low)}.assistant-nav .assistant-tab{appearance:none;min-width:0;min-height:30px;border:0;border-radius:8px;padding:0 10px;background:transparent;color:var(--md-sys-color-on-surface-variant);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;flex:1 1 0;font-size:11px;font-weight:700;letter-spacing:.01em}.assistant-nav .assistant-tab.active{background:var(--md-sys-color-surface-container-highest);color:var(--md-sys-color-on-surface);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--md-sys-color-primary) 34%,transparent),0 6px 12px color-mix(in srgb,var(--md-sys-color-primary) 18%,transparent)}.assistant-section,.assistant-card{border-radius:14px;border-color:color-mix(in srgb,var(--md-sys-color-primary) 20%,var(--md-sys-color-outline-variant));background:linear-gradient(160deg,color-mix(in srgb,var(--md-sys-color-primary-container) 16%,transparent),transparent 50%),var(--md-sys-color-surface-container-lowest);box-shadow:0 6px 18px color-mix(in srgb,var(--md-sys-color-shadow, var(--md-sys-color-on-surface)) 12%,transparent),inset 0 1px color-mix(in srgb,var(--md-sys-color-on-surface) 7%,transparent)}.suggestions-hero{margin:2px 0 4px;padding:10px 12px;border-radius:12px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 24%,var(--md-sys-color-outline-variant));background:linear-gradient(120deg,color-mix(in srgb,var(--md-sys-color-primary-container) 34%,transparent) 0%,transparent 52%),var(--md-sys-color-surface-container-low)}.suggestions-hero__label{font-size:10px;letter-spacing:.08em;text-transform:uppercase;font-weight:700;color:var(--md-sys-color-on-surface-variant);opacity:.88}.suggestions-hero__title{margin-top:2px;font-size:13px;font-weight:700;color:var(--md-sys-color-on-surface)}.suggestions-hero__detail{margin-top:4px;font-size:12px;line-height:1.4;color:color-mix(in srgb,var(--md-sys-color-on-surface) 78%,var(--md-sys-color-on-surface-variant))}.suggestions-content .suggestion-item{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:12px;padding:12px;border-radius:12px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 18%,var(--md-sys-color-outline-variant));border-color:color-mix(in srgb,var(--md-sys-color-primary) 18%,var(--md-sys-color-outline-variant));background:linear-gradient(140deg,color-mix(in srgb,var(--md-sys-color-primary-container) 16%,transparent),transparent 56%),var(--md-sys-color-surface-container-lowest);transition:transform .2s cubic-bezier(.25,.8,.25,1),border-color .2s ease,box-shadow .2s ease}.suggestions-list{display:flex;flex-direction:column;gap:10px}.suggestion-copy{min-width:0;display:grid;gap:4px}.suggestion-main{min-width:0;display:flex;align-items:center;flex-wrap:wrap;gap:8px}.suggestion-icon{width:18px;height:18px;font-size:18px;flex:0 0 auto;color:var(--md-sys-color-primary)}.suggestion-label{min-width:0;font-size:13px;font-weight:700;line-height:1.35;overflow-wrap:anywhere}.suggestion-group{padding:2px 6px;border-radius:999px;background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface-variant);font-size:10px;font-weight:700;line-height:1.2}.suggestion-desc{font-size:12px;line-height:1.35;color:var(--md-sys-color-on-surface-variant);overflow-wrap:anywhere}.suggestion-actions{display:inline-flex;align-items:center;justify-content:flex-end;gap:4px}.suggestion-action-btn,.suggestion-arrow{width:32px;height:32px;display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;color:var(--md-sys-color-on-surface-variant)}.suggestions-content .suggestion-item:hover,.suggestions-content .suggestion-item:focus-visible{border-color:color-mix(in srgb,var(--md-sys-color-primary) 58%,var(--md-sys-color-outline-variant));box-shadow:0 8px 18px color-mix(in srgb,var(--md-sys-color-primary) 18%,transparent),inset 0 0 0 1px color-mix(in srgb,var(--md-sys-color-primary) 28%,transparent);transform:translateY(-2px) scale(1.01)}.assistant-footer{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:8px;padding:10px 16px;border-top-color:color-mix(in srgb,var(--md-sys-color-primary) 20%,var(--md-sys-color-outline-variant));background:linear-gradient(180deg,color-mix(in srgb,var(--md-sys-color-primary-container) 16%,transparent),transparent 56%),var(--md-sys-color-surface-container-low)}.assistant-footer .task-footer{grid-column:1/-1}.composer-leading{width:30px;height:30px;display:inline-flex;align-items:center;justify-content:center;border-radius:999px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 30%,var(--md-sys-color-outline-variant));background:color-mix(in srgb,var(--md-sys-color-primary-container) 70%,var(--md-sys-color-surface-container-low));color:var(--md-sys-color-primary);box-shadow:0 4px 10px color-mix(in srgb,var(--md-sys-color-primary) 16%,transparent)}.composer-leading mat-icon{width:16px;height:16px;font-size:16px}.assistant-footer input{box-sizing:border-box;width:100%;min-width:0;height:34px;border:1px solid;border-radius:8px;padding:0 12px;color:var(--md-sys-color-on-surface);border-color:color-mix(in srgb,var(--md-sys-color-primary) 24%,var(--md-sys-color-outline-variant));background:var(--md-sys-color-surface);box-shadow:inset 0 1px 2px color-mix(in srgb,var(--md-sys-color-shadow, var(--md-sys-color-on-surface)) 12%,transparent)}.send-actions{min-width:36px;display:inline-flex;align-items:center;justify-content:center}.assistant-footer .send-btn{--mdc-icon-button-icon-size: 20px;--mdc-icon-button-state-layer-size: 36px;--mat-icon-button-state-layer-size: 36px;width:36px;height:36px;padding:8px;line-height:1;display:inline-flex;align-items:center;justify-content:center;border-color:color-mix(in srgb,var(--md-sys-color-primary) 24%,var(--md-sys-color-outline-variant));background:var(--md-sys-color-surface)}.assistant-footer .send-btn mat-icon{width:20px;height:20px;margin:0;font-size:20px;line-height:20px;display:inline-flex;align-items:center;justify-content:center}.assistant-footer .send-btn.ready{background:linear-gradient(135deg,color-mix(in srgb,var(--md-sys-color-primary-container) 84%,var(--md-sys-color-primary)),var(--md-sys-color-primary));color:var(--md-sys-color-on-primary);box-shadow:0 8px 18px color-mix(in srgb,var(--md-sys-color-primary) 30%,transparent)}.task-primary-btn{border-radius:12px;box-shadow:0 8px 18px color-mix(in srgb,var(--md-sys-color-primary) 24%,transparent)}@media(max-width:959px){.assistant-header{padding:12px 12px 10px}.assistant-section,.assistant-card{margin:4px 12px 10px}.assistant-header:after{left:12px;right:12px}.assistant-header .assistant-title{font-size:14px}.assistant-header .assistant-subtitle{font-size:10px}.assistant-footer{grid-template-columns:minmax(0,1fr) auto}.composer-leading{display:none}}.assistant-thought{margin-top:0;gap:10px;border-color:color-mix(in srgb,var(--md-sys-color-primary) 26%,var(--md-sys-color-outline-variant));background:linear-gradient(145deg,color-mix(in srgb,var(--md-sys-color-primary-container) 28%,transparent),transparent 58%),var(--md-sys-color-surface-container-low)}.assistant-thought-meta{display:inline-flex;align-items:center;gap:6px;font-size:11px;color:var(--md-sys-color-on-surface-variant)}.assistant-thought-meta mat-icon{width:15px;height:15px;font-size:15px;color:var(--md-sys-color-primary)}.assistant-thought-summary{font-size:13px;line-height:1.45;color:var(--md-sys-color-on-surface)}.assistant-thought-plan{border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 32%,var(--md-sys-color-outline-variant));border-radius:12px;padding:10px;background:var(--md-sys-color-surface-container-lowest);display:flex;flex-direction:column;gap:8px}.assistant-thought-plan-title{font-size:13px;font-weight:700;color:var(--md-sys-color-on-surface)}.assistant-thought-plan-actions{display:grid;grid-template-columns:repeat(auto-fit,minmax(0,1fr));gap:8px}.assistant-thought-plan-actions .mdc-button{min-width:0}.assistant-thought-plan-hint{font-size:11px;color:var(--md-sys-color-on-surface-variant);line-height:1.35}.assistant-thought-checklist{display:flex;flex-direction:column;gap:5px}.assistant-thought-checklist-item{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--md-sys-color-on-surface-variant)}.assistant-thought-checklist-item mat-icon{width:14px;height:14px;font-size:14px}.assistant-thought-shimmer{display:flex;flex-direction:column;gap:8px;margin-top:4px}.assistant-thought-shimmer .shimmer-line{height:12px;border-radius:4px;position:relative;overflow:hidden;background:var(--md-sys-color-surface-container-highest)}.assistant-thought-shimmer .shimmer-line:after{content:\"\";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--md-sys-color-primary) 8%,transparent),transparent);animation:assistantShimmerEffect 1.5s infinite}.assistant-thought-shimmer .shimmer-line-1{width:85%}.assistant-thought-shimmer .shimmer-line-2{width:92%}.assistant-thought-shimmer .shimmer-line-3{width:64%}@keyframes assistantShimmerEffect{to{transform:translate(100%)}}.assistant-flow{grid-template-columns:1fr;gap:6px}.flow-step{display:flex;align-items:flex-start;gap:8px;text-align:left;padding:7px 8px;border-radius:10px}.flow-step-index{width:18px;height:18px;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;font-size:10px;font-weight:700;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-highest);color:var(--md-sys-color-on-surface);flex:0 0 auto}.flow-step-content{min-width:0;display:flex;flex-direction:column;gap:1px}.flow-step-label{font-size:11px;font-weight:700;color:var(--md-sys-color-on-surface)}.flow-step-detail{font-size:11px;color:var(--md-sys-color-on-surface-variant);line-height:1.3}.flow-step.active .flow-step-index{border-color:color-mix(in srgb,var(--md-sys-color-primary) 60%,var(--md-sys-color-outline-variant));background:color-mix(in srgb,var(--md-sys-color-primary-container) 85%,var(--md-sys-color-surface-container-highest));color:var(--md-sys-color-on-primary-container)}.flow-step.done .flow-step-index{border-color:transparent;background:color-mix(in srgb,var(--md-sys-color-primary) 18%,var(--md-sys-color-surface-container-highest))}.task-timeline{margin-top:4px;display:grid;gap:6px}.task-timeline-item{display:flex;align-items:flex-start;gap:8px;border:1px solid var(--md-sys-color-outline-variant);border-radius:10px;padding:6px 8px;background:var(--md-sys-color-surface-container-low);opacity:.76}.task-timeline-item.active{opacity:1;border-color:color-mix(in srgb,var(--md-sys-color-primary) 40%,var(--md-sys-color-outline-variant));background:color-mix(in srgb,var(--md-sys-color-primary-container) 34%,var(--md-sys-color-surface-container-low))}.task-timeline-item.done{opacity:.9;border-color:color-mix(in srgb,var(--md-sys-color-primary) 24%,var(--md-sys-color-outline-variant))}.task-timeline-dot{width:18px;height:18px;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;font-size:10px;font-weight:700;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-highest);color:var(--md-sys-color-on-surface);flex:0 0 auto}.task-timeline-copy{min-width:0;display:flex;flex-direction:column;gap:1px}.task-timeline-title{font-size:11px;font-weight:700;color:var(--md-sys-color-on-surface)}.task-timeline-detail{font-size:11px;line-height:1.3;color:var(--md-sys-color-on-surface-variant)}.clarification-decision-head{display:inline-flex;align-items:center;width:100%;gap:6px;padding:8px 12px 0;box-sizing:border-box}.clarification-decision-index{width:18px;height:18px;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;font-size:10px;font-weight:700;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 35%,var(--md-sys-color-outline-variant));color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary-container) 68%,transparent)}.clarification-decision-type{font-size:10px;letter-spacing:.08em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant);opacity:.92}.clarification-decision-state{font-size:10px;font-weight:700;color:var(--md-sys-color-primary)}.clarification-option{border-color:color-mix(in srgb,var(--md-sys-color-primary) 20%,var(--md-sys-color-outline-variant));background:linear-gradient(145deg,color-mix(in srgb,var(--md-sys-color-primary-container) 16%,transparent),transparent 55%),var(--md-sys-color-surface-container-low)}.clarification-option.selected{border-color:color-mix(in srgb,var(--md-sys-color-primary) 56%,var(--md-sys-color-outline-variant));background:linear-gradient(145deg,color-mix(in srgb,var(--md-sys-color-primary-container) 44%,transparent),transparent 62%),var(--md-sys-color-surface-container);box-shadow:0 8px 16px color-mix(in srgb,var(--md-sys-color-primary) 18%,transparent)}.clarification-options-block{overflow:visible;padding-right:4px}@media(max-width:959px){.assistant-thought-plan-actions{grid-template-columns:1fr}}.ai-assistant-panel{width:min(604px,100vw - 18px)}.assistant-section,.assistant-card{margin:0;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 20%,var(--md-sys-color-outline-variant))}.assistant-section{min-height:0;padding:14px 16px;overflow:visible}.assistant-card{min-height:0;padding:14px 16px 16px;overflow:visible}.suggestions-area,.assistant-history,.loading-suggestions{overflow-y:auto;overflow-x:hidden}.section-header{min-width:0;display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:10px}.section-title{min-width:0;font-size:14px;font-weight:700;line-height:1.35;overflow-wrap:anywhere}.suggestions-actions{flex:0 0 auto;display:inline-flex;align-items:center}.review-area,.error-area,.success-area,.clarification-area{padding:0;overflow-y:auto;overflow-x:hidden;scrollbar-gutter:auto}.review-trust{margin:2px 0 4px}.trust-chip{max-width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.warnings-area,.review-summary,.review-diff,.apply-details,.clarification-options-block,.clarification-manual-toggle{width:100%;max-width:100%;min-width:0}.review-diff{padding:12px 14px}.review-diff-full{padding:10px;overflow-x:auto}.review-diff-block{min-width:0}.review-diff-block pre{overflow-wrap:anywhere;word-break:break-word}.clarification-options-block{padding:4px 2px 10px}.clarification-option{line-height:normal}:host ::ng-deep .clarification-option .mdc-button__label{line-height:1.35!important}.clarification-plain-label{padding:6px 12px 12px;font-size:14px;line-height:1.35}.clarification-manual-toggle{margin-top:10px;padding:10px 2px 0;flex-wrap:wrap;row-gap:6px}.suggestions-content .suggestion-actions{gap:6px}.suggestions-content .suggestion-arrow,.suggestions-content .suggestion-action-btn mat-icon,.suggestions-content .suggestion-arrow mat-icon{display:inline-flex;align-items:center;justify-content:center}:host ::ng-deep .assistant-quick-menu-panel{min-width:244px;max-width:min(90vw,320px);border-radius:14px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 26%,var(--md-sys-color-outline-variant));background:var(--md-sys-color-surface-container-high);box-shadow:0 12px 28px color-mix(in srgb,var(--md-sys-color-shadow, var(--md-sys-color-on-surface)) 32%,transparent),inset 0 1px color-mix(in srgb,var(--md-sys-color-on-surface) 6%,transparent);overflow:hidden;padding:6px}:host ::ng-deep .assistant-quick-menu-panel .mat-mdc-menu-item{min-height:36px;border-radius:10px;color:var(--md-sys-color-on-surface);font-size:12px;font-weight:500;margin:1px 0}:host ::ng-deep .assistant-quick-menu-panel .mat-mdc-menu-item .mat-icon{color:color-mix(in srgb,var(--md-sys-color-on-surface) 82%,var(--md-sys-color-on-surface-variant))}:host ::ng-deep .assistant-quick-menu-panel .mat-mdc-menu-item:hover:not([disabled]){background:color-mix(in srgb,var(--md-sys-color-primary-container) 45%,transparent)}:host ::ng-deep .assistant-quick-menu-panel .mat-mdc-menu-item:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:-2px}:host ::ng-deep .assistant-quick-menu-panel .assistant-quick-menu-danger{color:var(--md-sys-color-error)}:host ::ng-deep .assistant-quick-menu-panel .assistant-quick-menu-danger .mat-icon{color:var(--md-sys-color-error)}@media(max-width:959px){::ng-deep .ai-assistant-overlay-pane{top:12px!important;left:12px!important;width:calc(100vw - 24px)!important;height:calc(100vh - 24px)!important;max-width:calc(100vw - 24px);max-height:calc(100vh - 24px);transform:none!important}.ai-assistant-panel{width:calc(100vw - 48px);min-height:min(620px,100vh - 48px);max-height:calc(100vh - 48px)}.assistant-section,.assistant-card{margin:0}.assistant-card,.assistant-section{padding:12px}}.ai-trigger-btn{--mdc-icon-button-state-layer-size: 36px;width:36px;height:36px;border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-primary) 9%,transparent);border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 22%,transparent);color:var(--md-sys-color-primary);opacity:1}.ai-trigger-btn:hover:not(:disabled){background:color-mix(in srgb,var(--md-sys-color-primary) 16%,transparent);border-color:color-mix(in srgb,var(--md-sys-color-primary) 36%,transparent);color:var(--md-sys-color-on-primary-container)}.ai-trigger-btn:focus-visible,.assistant-close-btn:focus-visible,.assistant-tab:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.assistant-close-btn{width:28px;height:28px;color:var(--md-sys-color-on-surface-variant)}.assistant-close-btn:hover:not(:disabled){background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface)}.assistant-body{padding:12px 16px;overflow:hidden;min-height:0;flex:1;display:flex;flex-direction:column;gap:12px}.assistant-body>*{min-height:0}@media(max-width:959px){.assistant-nav{padding:8px 12px 0}.assistant-body,.assistant-footer{padding:10px 12px}.suggestions-content .suggestion-item{grid-template-columns:1fr;align-items:start}.suggestion-actions{justify-content:flex-start}}\n"] }]
|
|
8002
|
+
PraxisIconButtonComponent,
|
|
8003
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- Trigger Button -->\n<button\n praxisIconButton=\"auto_awesome\"\n size=\"compact\"\n cdkOverlayOrigin\n #trigger=\"cdkOverlayOrigin\"\n #triggerBtn\n (click)=\"open()\"\n [disabled]=\"isOpen\"\n class=\"ai-trigger-btn\"\n matTooltip=\"Assistente de Configura\u00E7\u00E3o\"\n aria-label=\"Abrir Assistente IA\"></button>\n\n<!-- Overlay Template -->\n<ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"trigger\"\n [cdkConnectedOverlayOpen]=\"isOpen\"\n [cdkConnectedOverlayHasBackdrop]=\"hasBackdrop\"\n [cdkConnectedOverlayPositions]=\"overlayPositions\"\n [cdkConnectedOverlayPush]=\"true\"\n [cdkConnectedOverlayViewportMargin]=\"12\"\n cdkConnectedOverlayPanelClass=\"ai-assistant-overlay-pane\"\n cdkConnectedOverlayBackdropClass=\"ai-assistant-backdrop\"\n (backdropClick)=\"close()\"\n (overlayOutsideClick)=\"close()\"\n (detach)=\"close()\">\n\n <div\n class=\"ai-assistant-panel\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"Assistente de Configura\u00E7\u00E3o\"\n [attr.aria-busy]=\"isBusyState() ? 'true' : null\"\n [cdkTrapFocus]=\"hasBackdrop\"\n [cdkTrapFocusAutoCapture]=\"hasBackdrop\"\n (keydown)=\"onKeydown($event)\"\n >\n\n <!-- HEADER -->\n <div class=\"assistant-header\">\n <div class=\"assistant-header__left\">\n <mat-icon class=\"magic-icon\">auto_awesome</mat-icon>\n <div class=\"assistant-title-group\">\n <div class=\"assistant-title\">Assistente de Configura\u00E7\u00E3o</div>\n <div class=\"assistant-subtitle\">Copiloto contextual para ajustes guiados</div>\n <div class=\"assistant-header-chips\">\n <span\n class=\"mode-chip\"\n [class.mock]=\"mockMode\"\n [matTooltip]=\"mockMode ? 'Sem chave de API: respostas de demonstra\u00E7\u00E3o' : 'Conectado ao assistente configurado'\"\n >\n {{ mockMode ? 'Mock' : 'Conectado' }}\n </span>\n <span\n class=\"policy-chip\"\n [class.strict]=\"isStrictRiskPolicy()\"\n [matTooltip]=\"getRiskPolicyTooltip()\"\n >\n {{ getRiskPolicyLabel() }}\n </span>\n </div>\n </div>\n </div>\n <div class=\"assistant-header__right\">\n <button\n praxisIconButton=\"close\"\n size=\"dense\"\n type=\"button\"\n class=\"assistant-close-btn\"\n (click)=\"close()\"\n aria-label=\"Fechar assistente\"\n matTooltip=\"Fechar assistente\"\n ></button>\n </div>\n </div>\n <div\n class=\"assistant-status\"\n [class.processing]=\"isBusyState()\"\n [class.pending]=\"state === 'clarification'\"\n [class.warning]=\"state === 'error'\"\n [class.success]=\"state === 'review' || state === 'success'\"\n [class.compact]=\"!shouldShowSystemStatusDetail()\"\n role=\"status\"\n [attr.aria-live]=\"getSystemStatusAriaLive()\"\n aria-atomic=\"true\"\n >\n <span class=\"assistant-status-dot\" aria-hidden=\"true\"></span>\n <div class=\"assistant-status-content\">\n <div class=\"assistant-status-label\">\n <span class=\"assistant-status-label-prefix\">Status:</span>\n <span>{{ getSystemStatusLabel() }}</span>\n @if (shouldShowSnapshotFallbackBadge()) {\n <span class=\"assistant-status-mode\">Snapshot</span>\n }\n </div>\n @if (shouldShowSystemStatusDetail()) {\n <div class=\"assistant-status-detail\">{{ getSystemStatusDetail() }}</div>\n }\n </div>\n </div>\n @if (shouldShowTaskFlow()) {\n <div class=\"assistant-flow\" role=\"list\" aria-label=\"Fluxo da proposta\">\n @for (step of flowSteps; track step) {\n <div\n class=\"flow-step\"\n role=\"listitem\"\n [class.active]=\"getFlowStepState(step.step) === 'active'\"\n [class.done]=\"getFlowStepState(step.step) === 'done'\"\n >\n <span class=\"flow-step-index\">{{ step.step }}</span>\n <span class=\"flow-step-content\">\n <span class=\"flow-step-label\">{{ step.label }}</span>\n <span class=\"flow-step-detail\">{{ getFlowStepDetail(step.step) }}</span>\n </span>\n </div>\n }\n </div>\n }\n <div class=\"assistant-nav\">\n <div\n class=\"assistant-tabs\"\n role=\"tablist\"\n aria-label=\"Se\u00E7\u00F5es do assistente\"\n (keydown)=\"onTabsKeydown($event)\"\n >\n @if (isTaskMode()) {\n <button\n class=\"assistant-tab\"\n type=\"button\"\n id=\"assistant-tab-task\"\n role=\"tab\"\n aria-label=\"Proposta atual\"\n [attr.aria-selected]=\"isActiveTab('task')\"\n aria-controls=\"assistant-panel-task\"\n [attr.tabindex]=\"isActiveTab('task') ? 0 : -1\"\n [class.active]=\"isActiveTab('task')\"\n (click)=\"setActiveTab('task')\"\n >\n Proposta\n @if (hasPendingClarification() && !isActiveTab('task')) {\n <span class=\"assistant-tab-badge\">1</span>\n }\n </button>\n }\n <button\n class=\"assistant-tab\"\n type=\"button\"\n id=\"assistant-tab-chat\"\n role=\"tab\"\n aria-label=\"Hist\u00F3rico\"\n [attr.aria-selected]=\"isActiveTab('chat')\"\n aria-controls=\"assistant-panel-chat\"\n [attr.tabindex]=\"isActiveTab('chat') ? 0 : -1\"\n [class.active]=\"isActiveTab('chat')\"\n (click)=\"setActiveTab('chat')\"\n >\n Hist\u00F3rico\n </button>\n <button\n class=\"assistant-tab\"\n type=\"button\"\n id=\"assistant-tab-suggestions\"\n role=\"tab\"\n aria-label=\"Sugest\u00F5es de melhoria\"\n [attr.aria-selected]=\"isActiveTab('suggestions')\"\n aria-controls=\"assistant-panel-suggestions\"\n [attr.tabindex]=\"isActiveTab('suggestions') ? 0 : -1\"\n [class.active]=\"isActiveTab('suggestions')\"\n (click)=\"setActiveTab('suggestions')\"\n >\n Sugest\u00F5es\n </button>\n </div>\n </div>\n\n <!-- BODY: Dynamic Content based on State -->\n <div class=\"assistant-body\">\n @if (shouldShowThoughtCard()) {\n <div class=\"assistant-thought assistant-section\">\n <div class=\"assistant-thought-meta\">\n <mat-icon>psychology</mat-icon>\n <span>{{ getThoughtTimingLabel() }}</span>\n </div>\n <div class=\"assistant-thought-summary\">{{ getThoughtSummary() }}</div>\n <div class=\"assistant-thought-plan\">\n <div class=\"assistant-thought-plan-title\">{{ getThoughtPlanTitle() }}</div>\n <div class=\"assistant-thought-plan-actions\">\n <button\n mat-stroked-button\n type=\"button\"\n class=\"thought-action-details\"\n (click)=\"openThoughtDetails()\"\n [attr.aria-label]=\"getThoughtDetailsLabel()\"\n [matTooltip]=\"getThoughtDetailsTooltip()\"\n >\n {{ getThoughtDetailsLabel() }}\n </button>\n @if (shouldShowThoughtPreviewAction()) {\n <button\n mat-flat-button\n color=\"primary\"\n type=\"button\"\n class=\"thought-action-preview\"\n (click)=\"openThoughtPreview()\"\n [matTooltip]=\"getThoughtPreviewTooltip()\"\n >\n Pr\u00E9via\n </button>\n }\n </div>\n <div class=\"assistant-thought-plan-hint\">{{ getThoughtActionHint() }}</div>\n @if (getThoughtChecklist(); as thoughtChecklist) {\n @if (thoughtChecklist.length) {\n <div class=\"assistant-thought-checklist\">\n @for (item of thoughtChecklist; track item) {\n <div class=\"assistant-thought-checklist-item\">\n <mat-icon>radio_button_unchecked</mat-icon>\n <span>{{ item }}</span>\n </div>\n }\n </div>\n }\n @if (isBusyState() && !thoughtChecklist.length) {\n <div class=\"assistant-thought-shimmer\">\n <div class=\"shimmer-line shimmer-line-1\"></div>\n <div class=\"shimmer-line shimmer-line-2\"></div>\n <div class=\"shimmer-line shimmer-line-3\"></div>\n </div>\n }\n }\n </div>\n </div>\n }\n @if (processingInfoVisible) {\n <div class=\"processing-banner\">\n <mat-spinner diameter=\"16\"></mat-spinner>\n <span>{{ aiExplanation || 'Analisando solicita\u00E7\u00E3o e preparando proposta...' }}</span>\n <button mat-button type=\"button\" class=\"processing-retry\" (click)=\"retryProcessing()\">Tentar novamente</button>\n </div>\n }\n @if (historyContext && isActiveTab('chat')) {\n <div\n class=\"assistant-history assistant-section\"\n id=\"assistant-panel-chat\"\n role=\"tabpanel\"\n aria-labelledby=\"assistant-tab-chat\"\n >\n <div class=\"section-header\">\n <div class=\"section-heading\">\n <div class=\"section-title\">Hist\u00F3rico</div>\n <div class=\"section-subtitle\">Sess\u00F5es recentes, pedidos reaproveit\u00E1veis e desfazer r\u00E1pido.</div>\n </div>\n <div class=\"history-actions\" role=\"group\" aria-label=\"A\u00E7\u00F5es do hist\u00F3rico\">\n <button\n mat-stroked-button\n type=\"button\"\n class=\"history-action-btn\"\n (click)=\"historyExpanded = !historyExpanded\"\n [matTooltip]=\"historyExpanded ? 'Recolher hist\u00F3rico' : 'Expandir hist\u00F3rico'\"\n [attr.aria-label]=\"historyExpanded ? 'Recolher hist\u00F3rico' : 'Expandir hist\u00F3rico'\"\n [disabled]=\"!historyWarnings.length && !historySessions.length && !activeHistoryMessages.length\"\n >\n <mat-icon>{{ historyExpanded ? 'expand_less' : 'expand_more' }}</mat-icon>\n <span>{{ historyExpanded ? 'Recolher' : 'Expandir' }}</span>\n </button>\n <button\n mat-stroked-button\n type=\"button\"\n class=\"history-action-btn\"\n (click)=\"startNewSession()\"\n matTooltip=\"Nova conversa\"\n aria-label=\"Nova conversa\"\n [disabled]=\"isBusyState()\"\n >\n <mat-icon>add_comment</mat-icon>\n <span>Nova conversa</span>\n </button>\n <button\n mat-stroked-button\n type=\"button\"\n (click)=\"clearHistory()\"\n matTooltip=\"Limpar hist\u00F3rico local\"\n aria-label=\"Limpar hist\u00F3rico local\"\n class=\"history-action-btn history-action-btn--danger\"\n [disabled]=\"!historySessions.length\"\n >\n <mat-icon>delete_outline</mat-icon>\n <span>Limpar</span>\n </button>\n </div>\n </div>\n @if (historyUndoDeleteSession) {\n <div class=\"history-undo\">\n <span>Sess\u00E3o removida.</span>\n <button mat-button type=\"button\" (click)=\"undoRemoveHistorySession()\">\n Desfazer\n </button>\n </div>\n }\n @if (historyExpanded && historyWarnings.length) {\n <div class=\"history-warnings\">\n <mat-icon>info</mat-icon>\n <div class=\"history-warnings-list\">\n @for (warning of historyWarnings; track warning) {\n <div>{{ warning }}</div>\n }\n <div class=\"history-warnings-hint\">\n Configure headers via API_CONFIG_STORAGE_OPTIONS no host.\n </div>\n </div>\n </div>\n }\n @if (historyExpanded && historySessions.length) {\n <div class=\"history-sessions\">\n @for (session of historySessions; track session.id) {\n <div\n class=\"history-session\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"selectHistorySession(session.id)\"\n (keydown)=\"onHistorySessionCardKeydown($event, session.id)\"\n [class.active]=\"session.id === activeHistorySession?.id\"\n [matTooltip]=\"getHistorySessionTooltip(session)\"\n [matTooltipDisabled]=\"!session.componentType && !session.componentId\"\n >\n <div class=\"history-session-main\">\n <span class=\"history-session-title\">{{ session.title }}</span>\n <div class=\"history-session-main-right\">\n <span class=\"history-session-time\">{{ session.updatedAt | date:'short' }}</span>\n <div class=\"history-session-tools\">\n <button\n praxisIconButton=\"edit_note\"\n size=\"dense\"\n type=\"button\"\n class=\"history-session-tool\"\n (click)=\"reuseHistorySessionPrompt(session.id, $event)\"\n matTooltip=\"Reusar \u00FAltimo pedido\"\n aria-label=\"Reusar \u00FAltimo pedido\"\n ></button>\n <button\n praxisIconButton=\"delete_outline\"\n size=\"dense\"\n type=\"button\"\n class=\"history-session-tool history-session-tool--danger\"\n (click)=\"removeHistorySession(session.id, $event)\"\n matTooltip=\"Excluir sess\u00E3o\"\n aria-label=\"Excluir sess\u00E3o\"\n ></button>\n </div>\n </div>\n </div>\n <div class=\"history-session-meta\">\n @if (session.componentType) {\n <span class=\"history-chip\">{{ session.componentType }}</span>\n }\n @if (session.componentId) {\n <span class=\"history-chip\">{{ session.componentId }}</span>\n }\n </div>\n </div>\n }\n </div>\n }\n @if (historyExpanded && !historySessions.length) {\n <div class=\"history-empty\">\n Nenhuma sess\u00E3o salva ainda.\n </div>\n }\n @if (historyExpanded && activeHistoryMessages.length) {\n <div class=\"history-messages\">\n @if (activeHistoryTotalMessages > activeHistoryMessages.length) {\n <div\n class=\"history-messages-hint\"\n >\n Mostrando \u00FAltimas {{ activeHistoryMessages.length }} de {{ activeHistoryTotalMessages }} mensagens.\n </div>\n }\n @for (msg of activeHistoryMessages; track msg.id) {\n <div\n class=\"history-message\"\n [class.user]=\"msg.role === 'user'\"\n [class.assistant]=\"msg.role === 'assistant'\"\n >\n <div class=\"history-message-header\">\n <span class=\"history-message-role\">{{ msg.role === 'user' ? 'Voc\u00EA' : 'Assistente' }}</span>\n <span class=\"history-message-time\">{{ msg.createdAt | date:'shortTime' }}</span>\n @if (msg.context?.usedRag) {\n <span\n class=\"history-rag\"\n matTooltip=\"Resposta baseada em contexto recuperado (RAG)\"\n >RAG</span>\n }\n </div>\n <div class=\"history-message-text\">{{ msg.text }}</div>\n </div>\n }\n </div>\n }\n @if (historyExpanded && historySessions.length && !activeHistoryMessages.length) {\n <div class=\"history-empty history-empty--panel\">\n Selecione uma sess\u00E3o para visualizar as mensagens.\n </div>\n }\n @if (historyExpanded) {\n <div class=\"history-helper\">\n O hist\u00F3rico \u00E9 local ao usu\u00E1rio e ao componente atual.\n </div>\n }\n </div>\n }\n\n @if (loadingSuggestions && isActiveTab('suggestions')) {\n <div\n class=\"loading-suggestions assistant-section\"\n id=\"assistant-panel-suggestions\"\n role=\"tabpanel\"\n aria-labelledby=\"assistant-tab-suggestions\"\n >\n <mat-spinner diameter=\"20\"></mat-spinner>\n <span>Carregando sugest\u00F5es de melhoria...</span>\n </div>\n }\n\n <!-- STATE: LISTENING (Suggestions) -->\n @if (state === 'listening' && isActiveTab('suggestions')) {\n <div\n class=\"suggestions-area assistant-section\"\n id=\"assistant-panel-suggestions\"\n role=\"tabpanel\"\n aria-labelledby=\"assistant-tab-suggestions\"\n >\n <div class=\"section-header\">\n <div class=\"section-title\">Sugest\u00F5es de melhoria</div>\n <div class=\"suggestions-actions\">\n <button praxisIconButton=\"refresh\" size=\"dense\" type=\"button\" (click)=\"refreshSuggestions()\" [disabled]=\"loadingSuggestions\" aria-label=\"Atualizar sugest\u00F5es\" matTooltip=\"Atualizar sugest\u00F5es\"></button>\n </div>\n </div>\n @if (!loadingSuggestions) {\n <div class=\"suggestions-hero\">\n <div class=\"suggestions-hero__label\">Contexto ativo</div>\n <div class=\"suggestions-hero__title\">{{ adapter.componentName || 'Componente atual' }}</div>\n <div class=\"suggestions-hero__detail\">{{ getSystemStatusDetail() }}</div>\n </div>\n }\n @if (suggestionsWarnings.length) {\n <div class=\"warnings-area\">\n <mat-icon class=\"warnings-icon\">warning_amber</mat-icon>\n <div class=\"warnings-content\">\n <div class=\"warnings-title\">Avisos</div>\n <div class=\"warnings-list\">\n @for (warning of suggestionsWarnings; track warning) {\n <div>{{ warning }}</div>\n }\n </div>\n </div>\n </div>\n }\n @if (!loadingSuggestions && (richSuggestions.length || hasDismissedSuggestions())) {\n <div class=\"suggestions-content\">\n @if (hasDismissedSuggestions()) {\n <div class=\"suggestions-filter\">\n <span>{{ getDismissedSuggestionCount() }} oculta(s)</span>\n <button mat-button type=\"button\" (click)=\"restoreDismissedSuggestions()\">\n Restaurar\n </button>\n </div>\n }\n @if (getVisibleSuggestions().length) {\n <div class=\"suggestions-list\">\n @for (sug of getVisibleSuggestions(); track sug.id) {\n <div\n class=\"suggestion-item\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"'Selecionar sugest\u00E3o: ' + sug.label\"\n (click)=\"selectSuggestion(sug)\"\n (keydown)=\"onSuggestionCardKeydown($event, sug)\"\n >\n <div class=\"suggestion-copy\">\n <div class=\"suggestion-main\">\n @if (sug.icon) {\n <mat-icon class=\"suggestion-icon\">{{ sug.icon }}</mat-icon>\n }\n <span class=\"suggestion-label\">{{ sug.label }}</span>\n @if (sug.group) {\n <span class=\"suggestion-group\">{{ sug.group }}</span>\n }\n </div>\n @if (sug.description) {\n <div class=\"suggestion-desc\">{{ sug.description }}</div>\n }\n </div>\n <div class=\"suggestion-actions\">\n <span class=\"suggestion-arrow\" aria-hidden=\"true\">\n <mat-icon>chevron_right</mat-icon>\n </span>\n <button\n praxisIconButton=\"edit\"\n size=\"dense\"\n type=\"button\"\n class=\"suggestion-action-btn\"\n (click)=\"prepareSuggestionPrompt(sug, $event)\"\n matTooltip=\"Refinar pedido\"\n aria-label=\"Refinar pedido\"\n ></button>\n <button\n praxisIconButton=\"visibility_off\"\n size=\"dense\"\n type=\"button\"\n class=\"suggestion-action-btn suggestion-action-btn--danger\"\n (click)=\"dismissSuggestion(sug, $event)\"\n matTooltip=\"Ocultar sugest\u00E3o\"\n aria-label=\"Ocultar sugest\u00E3o\"\n ></button>\n </div>\n </div>\n }\n </div>\n } @else {\n <div class=\"suggestions-empty suggestions-empty--inline\">\n Todas as sugest\u00F5es foram ocultadas.\n </div>\n }\n </div>\n }\n @if (!loadingSuggestions && !richSuggestions.length) {\n <div class=\"suggestions-empty\">\n Nenhuma sugest\u00E3o dispon\u00EDvel no momento.\n </div>\n }\n @if (!loadingSuggestions && !richSuggestions.length) {\n <div class=\"suggestions-helper\">\n Selecione uma sugest\u00E3o acima ou descreva uma altera\u00E7\u00E3o no campo inferior.\n </div>\n }\n </div>\n }\n\n <!-- STATE: CLARIFICATION (Two-Step Flow) -->\n @if (state === 'clarification' && isActiveTab('task')) {\n <div\n class=\"clarification-area assistant-card\"\n id=\"assistant-panel-task\"\n role=\"tabpanel\"\n aria-labelledby=\"assistant-tab-task\"\n >\n @if (!shouldShowThoughtCard()) {\n <div class=\"task-header\">\n <div class=\"task-title\">{{ getTaskTitle() }}</div>\n <div class=\"task-subtitle\">{{ getTaskSubtitle() }}</div>\n @if (clarificationOptions.length > 1 && getTaskSelectionSummary(); as selectionSummary) {\n <div class=\"task-meta\">\n <span class=\"task-meta-label\">Selecionado:</span>\n <span class=\"task-meta-value\">{{ selectionSummary }}</span>\n </div>\n }\n @if (shouldShowTaskSteps()) {\n <div class=\"task-steps\">\n <span class=\"task-step active\">1 Dados</span>\n <span class=\"task-step\">2 Layout</span>\n <span class=\"task-step\">3 Revis\u00E3o</span>\n </div>\n }\n </div>\n }\n @if (clarificationResponseType === 'context') {\n <div class=\"context-only\">\n <mat-spinner diameter=\"24\"></mat-spinner>\n <div class=\"context-only-hint\">Buscando contexto adicional...</div>\n </div>\n }\n <ng-template #clarificationOptionContent let-opt let-index=\"index\" let-compact=\"compact\">\n @if (!compact) {\n <div class=\"clarification-decision-head\">\n <span class=\"clarification-decision-index\">{{ index + 1 }}</span>\n <span class=\"clarification-decision-type\">{{ getClarificationOptionKindLabel(opt) }}</span>\n <span class=\"spacer\"></span>\n @if (isClarificationSelected(opt)) {\n <span class=\"clarification-decision-state\">Selecionado</span>\n }\n </div>\n }\n @switch (getClarificationOptionLayout(opt)) {\n @case ('endpoint') {\n <div class=\"clarification-card\">\n <div class=\"clarification-card-header\">\n <mat-icon class=\"endpoint-icon\">{{ getEndpointIcon(opt) }}</mat-icon>\n @if (getEndpointMethod(opt); as method) {\n <span class=\"endpoint-method\" [attr.data-method]=\"method\">{{ method }}</span>\n }\n <span class=\"endpoint-label\">{{ opt.label }}</span>\n <span class=\"spacer\"></span>\n <mat-icon class=\"select-indicator\">\n {{ isClarificationSelected(opt) ? 'check_circle' : 'radio_button_unchecked' }}\n </mat-icon>\n </div>\n <div class=\"clarification-card-body\">\n @if (getEndpointPath(opt); as path) {\n <div class=\"endpoint-path\">{{ path }}</div>\n }\n @if (opt.contextHints?.description) {\n <div\n class=\"endpoint-description\"\n [matTooltip]=\"getDescriptionTooltip(opt)\"\n [matTooltipDisabled]=\"!shouldShowDescriptionTooltip(opt)\"\n >\n {{ opt.contextHints?.description }}\n </div>\n }\n </div>\n </div>\n }\n @case ('color') {\n <div class=\"clarification-color\">\n <span\n class=\"color-swatch\"\n [style.background]=\"getSafeHexColor(opt) || 'var(--md-sys-color-surface-container-highest)'\"\n ></span>\n <div class=\"color-meta\">\n <span class=\"color-label\">{{ opt.label }}</span>\n @if (opt.contextHints?.hexColor) {\n <span class=\"color-value\">{{ opt.contextHints?.hexColor }}</span>\n }\n </div>\n </div>\n }\n @case ('description') {\n <div class=\"clarification-description\">\n <span class=\"clarification-label\">{{ opt.label }}</span>\n @if (opt.contextHints?.description) {\n <span\n class=\"clarification-subtitle\"\n [matTooltip]=\"getDescriptionTooltip(opt)\"\n [matTooltipDisabled]=\"!shouldShowDescriptionTooltip(opt)\"\n >\n {{ opt.contextHints?.description }}\n </span>\n }\n </div>\n }\n @default {\n <span class=\"clarification-plain-label\">{{ opt.label }}</span>\n }\n }\n </ng-template>\n @if (warnings.length) {\n <div class=\"warnings-area\">\n <mat-icon class=\"warnings-icon\">warning_amber</mat-icon>\n <div class=\"warnings-content\">\n <div class=\"warnings-title\">Avisos</div>\n <div class=\"warnings-list\">\n @for (warning of warnings; track warning) {\n <div>{{ warning }}</div>\n }\n </div>\n </div>\n </div>\n }\n @if (clarificationQuestions.length) {\n <div\n class=\"clarification-questions\"\n [class.attention-highlight]=\"highlightClarificationDetails && !clarificationOptions.length\"\n >\n @for (question of clarificationQuestions; track question; let i = $index) {\n <div class=\"clarification-question\">\n <div class=\"clarification-question-label\">{{ question }}</div>\n <input\n type=\"text\"\n [(ngModel)]=\"clarificationAnswers[i]\"\n [placeholder]=\"'Resposta ' + (i + 1)\"\n autocomplete=\"off\">\n </div>\n }\n </div>\n }\n @if (clarificationOptions.length) {\n <div\n class=\"clarification-options-block\"\n [class.attention-highlight]=\"highlightClarificationDetails\"\n >\n <div class=\"clarification-options-title\">\n {{ clarificationOptions.length === 1 ? 'Decis\u00E3o sugerida' : 'Decis\u00F5es sugeridas' }}\n </div>\n @if (clarificationOptions.length === 1) {\n <div class=\"clarification-options-hint\">\n Etapa 2 de 4: confirme a melhor op\u00E7\u00E3o para continuar.\n </div>\n }\n @if (clarificationOptions.length > 1) {\n <div class=\"clarification-options-hint\">\n Etapa 2 de 4: selecione a alternativa mais aderente para gerar a proposta.\n </div>\n }\n @if (clarificationResponseType === 'confirm') {\n <div\n class=\"clarification-buttons\"\n [class.list]=\"clarificationPresentation === 'list'\"\n >\n @for (opt of clarificationOptions; track opt.value; let i = $index) {\n <button\n mat-button\n type=\"button\"\n (click)=\"onClarificationOptionClick(opt)\"\n class=\"clarification-option\"\n [class.selected]=\"isClarificationSelected(opt)\"\n [matTooltip]=\"getClarificationTooltip(opt)\"\n [matTooltipDisabled]=\"!shouldShowClarificationTooltip(opt) || isEndpointOption(opt)\"\n >\n <ng-container *ngTemplateOutlet=\"clarificationOptionContent; context: { $implicit: opt, index: i, compact: false }\"></ng-container>\n </button>\n }\n </div>\n }\n @if (clarificationSelectionMode === 'multiple') {\n <div\n class=\"clarification-buttons\"\n [class.list]=\"clarificationPresentation === 'list'\"\n >\n @for (opt of clarificationOptions; track opt.value; let i = $index) {\n <button\n mat-button\n type=\"button\"\n (click)=\"onClarificationOptionClick(opt)\"\n [class.selected]=\"isClarificationSelected(opt)\"\n class=\"clarification-option\"\n [matTooltip]=\"getClarificationTooltip(opt)\"\n [matTooltipDisabled]=\"!shouldShowClarificationTooltip(opt) || isEndpointOption(opt)\"\n >\n <ng-container *ngTemplateOutlet=\"clarificationOptionContent; context: { $implicit: opt, index: i, compact: false }\"></ng-container>\n </button>\n }\n </div>\n }\n @if (clarificationResponseType !== 'confirm' && clarificationSelectionMode === 'single' && clarificationPresentation !== 'chips') {\n <div\n class=\"clarification-buttons\"\n [class.list]=\"clarificationPresentation === 'list'\"\n >\n @for (opt of clarificationOptions; track opt.value; let i = $index) {\n <button\n mat-button\n type=\"button\"\n (click)=\"onClarificationOptionClick(opt)\"\n class=\"clarification-option\"\n [class.selected]=\"isClarificationSelected(opt)\"\n [matTooltip]=\"getClarificationTooltip(opt)\"\n [matTooltipDisabled]=\"!shouldShowClarificationTooltip(opt) || isEndpointOption(opt)\"\n >\n <ng-container *ngTemplateOutlet=\"clarificationOptionContent; context: { $implicit: opt, index: i, compact: false }\"></ng-container>\n </button>\n }\n </div>\n }\n @if (clarificationResponseType !== 'confirm' && clarificationSelectionMode === 'single' && clarificationPresentation === 'chips') {\n <div\n class=\"clarification-chips\"\n >\n @for (opt of clarificationOptions; track opt.value; let i = $index) {\n @if (isEndpointOption(opt)) {\n <button\n mat-button\n type=\"button\"\n class=\"clarification-option clarification-card-button\"\n (click)=\"onClarificationOptionClick(opt)\"\n [class.selected]=\"isClarificationSelected(opt)\"\n [matTooltip]=\"getClarificationTooltip(opt)\"\n [matTooltipDisabled]=\"!shouldShowClarificationTooltip(opt) || isEndpointOption(opt)\"\n >\n <ng-container *ngTemplateOutlet=\"clarificationOptionContent; context: { $implicit: opt, index: i, compact: false }\"></ng-container>\n </button>\n } @else {\n <mat-chip\n (click)=\"onClarificationOptionClick(opt)\"\n [matTooltip]=\"getClarificationTooltip(opt)\"\n [matTooltipDisabled]=\"!shouldShowClarificationTooltip(opt)\"\n class=\"clarification-chip\"\n >\n <ng-container *ngTemplateOutlet=\"clarificationOptionContent; context: { $implicit: opt, index: i, compact: true }\"></ng-container>\n </mat-chip>\n }\n }\n </div>\n }\n </div>\n }\n @if (clarificationAllowCustom && clarificationResponseType !== 'context') {\n <div\n class=\"clarification-manual-toggle\"\n >\n <span class=\"clarification-manual-label\">N\u00E3o encontrou o recurso?</span>\n <button mat-button type=\"button\" (click)=\"toggleManualInput()\">\n {{ showManualInput ? 'Ocultar resposta manual' : 'Responder manualmente' }}\n </button>\n </div>\n }\n @if (clarificationAllowCustom && showManualInput && clarificationResponseType !== 'context') {\n <div\n class=\"clarification-free\"\n >\n <input\n type=\"text\"\n [(ngModel)]=\"clarificationFreeText\"\n placeholder=\"Digite sua resposta\u2026\"\n autocomplete=\"off\"\n (keydown.enter)=\"confirmTaskAction()\"\n />\n </div>\n }\n @if (clarificationAllowCustom && showManualInput && clarificationResponseType !== 'context') {\n <div\n class=\"clarification-free-hint\"\n >\n Pressione Enter para enviar.\n </div>\n }\n </div>\n }\n\n <!-- STATE: REVIEW (Diff/Explanation) -->\n @if (state === 'review' && isActiveTab('task')) {\n <div\n class=\"review-area assistant-card\"\n id=\"assistant-panel-task\"\n role=\"tabpanel\"\n aria-labelledby=\"assistant-tab-task\"\n >\n @if (!shouldShowThoughtCard()) {\n <div class=\"task-header\">\n <div class=\"task-title\">{{ getTaskTitle() }}</div>\n <div class=\"task-subtitle\">{{ getTaskSubtitle() }}</div>\n @if (clarificationOptions.length > 1 && getTaskSelectionSummary(); as selectionSummary) {\n <div class=\"task-meta\">\n <span class=\"task-meta-label\">Selecionado:</span>\n <span class=\"task-meta-value\">{{ selectionSummary }}</span>\n </div>\n }\n @if (shouldShowTaskSteps()) {\n <div class=\"task-steps\">\n <span class=\"task-step\">1 Dados</span>\n <span class=\"task-step\">2 Layout</span>\n <span class=\"task-step active\">3 Revis\u00E3o</span>\n </div>\n }\n </div>\n }\n @if (warnings.length) {\n <div class=\"warnings-area\">\n <mat-icon class=\"warnings-icon\">warning_amber</mat-icon>\n <div class=\"warnings-content\">\n <div class=\"warnings-title\">Avisos</div>\n <div class=\"warnings-list\">\n @for (warning of warnings; track warning) {\n <div>{{ warning }}</div>\n }\n </div>\n </div>\n </div>\n }\n <div class=\"review-trust\">\n <span class=\"trust-chip\" [matTooltip]=\"getScopeTooltip()\">{{ getScopeLabel() }}</span>\n <span class=\"trust-chip\" [matTooltip]=\"getConfidenceTooltip()\">{{ getConfidenceLabel() }}</span>\n <span class=\"trust-chip risk-chip\" [class.medium]=\"getReviewRiskLevel() === 'm\u00E9dio'\" [class.high]=\"getReviewRiskLevel() === 'alto'\">\n Risco {{ getReviewRiskLevel() }}\n </span>\n </div>\n <div class=\"review-summary\" [class.attention-highlight]=\"highlightReviewDetails\">\n <div class=\"review-summary-title\">Resumo da proposta</div>\n <div class=\"review-summary-line\">{{ getReviewSummary() }}</div>\n </div>\n <div class=\"review-diff\">\n <div class=\"review-diff-title\">Pr\u00E9via de mudan\u00E7as</div>\n @if (pendingDiff.length) {\n <div class=\"review-diff-summary\">\n @for (line of getDiffSummaryLines(); track line) {\n <div class=\"review-diff-line\">{{ line }}</div>\n }\n @if (pendingDiff.length > 3) {\n <div class=\"review-diff-more\">\u2026 +{{ pendingDiff.length - 3 }} mudan\u00E7as</div>\n }\n </div>\n <button mat-stroked-button type=\"button\" class=\"review-diff-toggle\" (click)=\"toggleFullDiff()\">\n {{ getDiffToggleLabel() }}\n </button>\n } @else {\n <div class=\"review-diff-empty\">\n N\u00E3o foi poss\u00EDvel gerar um diff estruturado. Revise o resumo e aplique com cautela.\n </div>\n }\n @if (showFullDiff && pendingDiff.length) {\n <div class=\"review-diff-full\">\n @for (diff of pendingDiff; track diff.path) {\n <div class=\"review-diff-block\">\n <div class=\"review-diff-path\">{{ diff.path }}</div>\n <div class=\"review-diff-label\">Antes:</div>\n <pre>{{ diff.before | json }}</pre>\n <div class=\"review-diff-label\">Depois:</div>\n <pre>{{ diff.after | json }}</pre>\n </div>\n }\n </div>\n }\n </div>\n @if (aiExplanation.trim()) {\n <div class=\"ai-explanation\">\n {{ aiExplanation }}\n </div>\n }\n </div>\n }\n\n <!-- STATE: ERROR -->\n @if (state === 'error' && (isActiveTab('task') || (!isTaskMode() && isActiveTab('suggestions')))) {\n <div\n class=\"error-area assistant-card\"\n [attr.id]=\"isTaskMode() ? 'assistant-panel-task' : 'assistant-panel-suggestions'\"\n role=\"tabpanel\"\n [attr.aria-labelledby]=\"isTaskMode() ? 'assistant-tab-task' : 'assistant-tab-suggestions'\"\n >\n <div class=\"error-msg\">\n <mat-icon color=\"warn\">error_outline</mat-icon>\n <span>{{ errorMsg }}</span>\n </div>\n @if (warnings.length) {\n <div class=\"warnings-area\">\n <mat-icon class=\"warnings-icon\">warning_amber</mat-icon>\n <div class=\"warnings-content\">\n <div class=\"warnings-title\">Avisos</div>\n <div class=\"warnings-list\">\n @for (warning of warnings; track warning) {\n <div>{{ warning }}</div>\n }\n </div>\n </div>\n </div>\n }\n @if (shouldShowApplyDetails()) {\n <div class=\"apply-details\">\n <div class=\"apply-details-header\">\n <div class=\"apply-details-title\">Detalhes da aplica\u00E7\u00E3o</div>\n @if (allowManualPatchEdit) {\n <div class=\"apply-details-actions\">\n <button mat-button type=\"button\" (click)=\"togglePatchPathEditor()\" [disabled]=\"!pendingPatch\">\n {{ patchPathEditorExpanded ? 'Ocultar paths' : 'Editar por path' }}\n </button>\n <button mat-button type=\"button\" (click)=\"togglePatchEditor()\" [disabled]=\"!pendingPatch\">\n {{ patchEditorExpanded ? 'Ocultar editor' : 'Editar patch' }}\n </button>\n </div>\n }\n </div>\n @if (lastApplyAt) {\n <div class=\"apply-details-meta\">\n \u00DAltima tentativa: {{ lastApplyAt | date:'short' }}\n </div>\n }\n @if (getApplyPaths().length) {\n <div class=\"apply-paths\">\n @for (path of getApplyPaths(); track path) {\n <span class=\"apply-path-chip\">{{ path }}</span>\n }\n </div>\n }\n @if (applyWarnings.length) {\n <div class=\"apply-warnings\">\n <div class=\"apply-warnings-title\">Avisos da aplica\u00E7\u00E3o</div>\n <div class=\"apply-warnings-list\">\n @for (warning of applyWarnings; track warning) {\n <div>{{ warning }}</div>\n }\n </div>\n </div>\n }\n @if (allowManualPatchEdit && patchPathEditorExpanded) {\n <div class=\"patch-path-editor\">\n <div class=\"patch-editor-label\">Editar por path</div>\n <div class=\"patch-editor-hint\">Texto simples vira string; para for\u00E7ar texto em true/false/n\u00FAmero, use aspas.</div>\n @if (!getEditablePatchPathEdits().length) {\n <div class=\"patch-path-editor-empty\">\n Nenhum path edit\u00E1vel dispon\u00EDvel para este patch.\n </div>\n }\n @if (getEditablePatchPathEdits().length) {\n <div class=\"patch-path-rows\">\n @for (edit of getEditablePatchPathEdits(); track edit.path; let i = $index) {\n <div class=\"patch-path-row\">\n <div class=\"patch-path-label\">{{ edit.path }}</div>\n <input\n type=\"text\"\n [(ngModel)]=\"patchPathEdits[i].valueText\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n />\n @if (patchPathEdits[i].error) {\n <div class=\"patch-editor-error\">{{ patchPathEdits[i].error }}</div>\n }\n </div>\n }\n </div>\n }\n @if (patchPathEditorError) {\n <div class=\"patch-editor-error\">{{ patchPathEditorError }}</div>\n }\n <div class=\"patch-editor-actions\">\n <button mat-button type=\"button\" (click)=\"resetPatchPathEdits()\">\n Restaurar valores\n </button>\n <button mat-button type=\"button\" (click)=\"applyPathEditsToPatch()\">\n Aplicar no patch\n </button>\n <button mat-flat-button color=\"primary\" type=\"button\" (click)=\"reapplyPathEdits()\">\n Reaplicar por path\n </button>\n </div>\n </div>\n }\n @if (allowManualPatchEdit && patchEditorExpanded) {\n <div class=\"patch-editor\">\n <label class=\"patch-editor-label\">Patch JSON</label>\n <textarea\n [(ngModel)]=\"patchEditorText\"\n spellcheck=\"false\"\n ></textarea>\n @if (patchEditorError) {\n <div class=\"patch-editor-error\">{{ patchEditorError }}</div>\n }\n <div class=\"patch-editor-actions\">\n <button mat-button type=\"button\" (click)=\"resetPatchEditor()\">\n Restaurar original\n </button>\n <button mat-flat-button color=\"primary\" type=\"button\" (click)=\"reapplyEditedPatch()\">\n Reaplicar patch\n </button>\n </div>\n </div>\n }\n </div>\n }\n <div class=\"review-actions\">\n <button mat-button (click)=\"close()\">Fechar</button>\n <button mat-stroked-button (click)=\"retry()\">Tentar Novamente</button>\n </div>\n </div>\n }\n\n <!-- STATE: SUCCESS -->\n @if (state === 'success' && (isActiveTab('task') || (!isTaskMode() && isActiveTab('suggestions')))) {\n <div\n class=\"success-area assistant-card\"\n [attr.id]=\"isTaskMode() ? 'assistant-panel-task' : 'assistant-panel-suggestions'\"\n role=\"tabpanel\"\n [attr.aria-labelledby]=\"isTaskMode() ? 'assistant-tab-task' : 'assistant-tab-suggestions'\"\n >\n <div class=\"success-msg\">\n <mat-icon class=\"success-icon\">check_circle</mat-icon>\n <span>{{ aiExplanation || 'Configura\u00E7\u00E3o atualizada.' }}</span>\n </div>\n @if (warnings.length) {\n <div class=\"warnings-area\">\n <mat-icon class=\"warnings-icon\">warning_amber</mat-icon>\n <div class=\"warnings-content\">\n <div class=\"warnings-title\">Avisos</div>\n <div class=\"warnings-list\">\n @for (warning of warnings; track warning) {\n <div>{{ warning }}</div>\n }\n </div>\n </div>\n </div>\n }\n @if (shouldShowApplyDetails()) {\n <div class=\"apply-details\">\n <div class=\"apply-details-header\">\n <div class=\"apply-details-title\">Detalhes da aplica\u00E7\u00E3o</div>\n @if (allowManualPatchEdit) {\n <div class=\"apply-details-actions\">\n <button mat-button type=\"button\" (click)=\"togglePatchPathEditor()\" [disabled]=\"!pendingPatch\">\n {{ patchPathEditorExpanded ? 'Ocultar paths' : 'Editar por path' }}\n </button>\n <button mat-button type=\"button\" (click)=\"togglePatchEditor()\" [disabled]=\"!pendingPatch\">\n {{ patchEditorExpanded ? 'Ocultar editor' : 'Editar e reaplicar' }}\n </button>\n </div>\n }\n </div>\n @if (lastApplyAt) {\n <div class=\"apply-details-meta\">\n Aplicado em {{ lastApplyAt | date:'short' }}\n </div>\n }\n @if (getApplyPaths().length) {\n <div class=\"apply-paths\">\n @for (path of getApplyPaths(); track path) {\n <span class=\"apply-path-chip\">{{ path }}</span>\n }\n </div>\n }\n @if (applyWarnings.length) {\n <div class=\"apply-warnings\">\n <div class=\"apply-warnings-title\">Avisos da aplica\u00E7\u00E3o</div>\n <div class=\"apply-warnings-list\">\n @for (warning of applyWarnings; track warning) {\n <div>{{ warning }}</div>\n }\n </div>\n </div>\n }\n @if (allowManualPatchEdit && patchPathEditorExpanded) {\n <div class=\"patch-path-editor\">\n <div class=\"patch-editor-label\">Editar por path</div>\n <div class=\"patch-editor-hint\">Texto simples vira string; para for\u00E7ar texto em true/false/n\u00FAmero, use aspas.</div>\n @if (!getEditablePatchPathEdits().length) {\n <div class=\"patch-path-editor-empty\">\n Nenhum path edit\u00E1vel dispon\u00EDvel para este patch.\n </div>\n }\n @if (getEditablePatchPathEdits().length) {\n <div class=\"patch-path-rows\">\n @for (edit of getEditablePatchPathEdits(); track edit.path; let i = $index) {\n <div class=\"patch-path-row\">\n <div class=\"patch-path-label\">{{ edit.path }}</div>\n <input\n type=\"text\"\n [(ngModel)]=\"patchPathEdits[i].valueText\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n />\n @if (patchPathEdits[i].error) {\n <div class=\"patch-editor-error\">{{ patchPathEdits[i].error }}</div>\n }\n </div>\n }\n </div>\n }\n @if (patchPathEditorError) {\n <div class=\"patch-editor-error\">{{ patchPathEditorError }}</div>\n }\n <div class=\"patch-editor-actions\">\n <button mat-button type=\"button\" (click)=\"resetPatchPathEdits()\">\n Restaurar valores\n </button>\n <button mat-button type=\"button\" (click)=\"applyPathEditsToPatch()\">\n Aplicar no patch\n </button>\n <button mat-flat-button color=\"primary\" type=\"button\" (click)=\"reapplyPathEdits()\">\n Reaplicar por path\n </button>\n </div>\n </div>\n }\n @if (allowManualPatchEdit && patchEditorExpanded) {\n <div class=\"patch-editor\">\n <label class=\"patch-editor-label\">Patch JSON</label>\n <textarea\n [(ngModel)]=\"patchEditorText\"\n spellcheck=\"false\"\n ></textarea>\n @if (patchEditorError) {\n <div class=\"patch-editor-error\">{{ patchEditorError }}</div>\n }\n <div class=\"patch-editor-actions\">\n <button mat-button type=\"button\" (click)=\"resetPatchEditor()\">\n Restaurar original\n </button>\n <button mat-flat-button color=\"primary\" type=\"button\" (click)=\"reapplyEditedPatch()\">\n Reaplicar patch\n </button>\n </div>\n </div>\n }\n </div>\n }\n <button mat-button color=\"warn\" (click)=\"undoLastChange()\">\n <mat-icon>undo</mat-icon> Desfazer\n </button>\n </div>\n }\n\n </div>\n\n <div class=\"assistant-footer\">\n @if (!isTaskMode()) {\n <button\n praxisIconButton=\"add\"\n size=\"dense\"\n type=\"button\"\n class=\"composer-leading composer-leading-btn\"\n [matMenuTriggerFor]=\"assistantQuickMenu\"\n aria-label=\"Abrir a\u00E7\u00F5es r\u00E1pidas\"\n matTooltip=\"A\u00E7\u00F5es r\u00E1pidas\"\n ></button>\n <input\n #inputEl\n type=\"text\"\n [(ngModel)]=\"userPrompt\"\n [disabled]=\"state === 'processing' || state === 'applying'\"\n placeholder=\"Descreva a altera\u00E7\u00E3o que deseja aplicar\u2026\"\n autocomplete=\"off\"\n />\n <div class=\"send-actions\">\n @if (state === 'listening') {\n <button\n praxisIconButton=\"arrow_upward\"\n size=\"compact\"\n [appearance]=\"userPrompt.trim() ? 'filled' : 'plain'\"\n class=\"send-btn\"\n (click)=\"submitPrompt()\"\n [disabled]=\"!userPrompt.trim()\"\n [class.ready]=\"!!userPrompt.trim()\"\n aria-label=\"Enviar pedido\"\n ></button>\n }\n @if (state === 'processing' || state === 'applying') {\n <mat-spinner diameter=\"20\"></mat-spinner>\n }\n </div>\n } @else {\n <div class=\"task-footer\">\n <div class=\"task-footer-left\">\n <button mat-button type=\"button\" (click)=\"handleTaskSecondary()\">{{ getTaskCancelLabel() }}</button>\n @if (state === 'review') {\n <button\n mat-stroked-button\n type=\"button\"\n (click)=\"retry()\"\n >\n {{ getTaskSecondaryLabel() }}\n </button>\n }\n </div>\n <div class=\"task-footer-right\">\n <button\n class=\"task-primary-btn\"\n mat-flat-button\n color=\"primary\"\n type=\"button\"\n (click)=\"confirmTaskAction()\"\n [disabled]=\"isTaskPrimaryDisabled()\"\n >\n {{ getTaskPrimaryLabel() }}\n </button>\n @if (state === 'processing' || state === 'applying') {\n <mat-spinner diameter=\"20\"></mat-spinner>\n }\n </div>\n </div>\n }\n </div>\n\n <mat-menu #assistantQuickMenu=\"matMenu\" panelClass=\"assistant-quick-menu-panel\">\n <button mat-menu-item type=\"button\" (click)=\"setActiveTab('chat')\">\n <mat-icon>history</mat-icon>\n <span>Hist\u00F3rico</span>\n </button>\n <button mat-menu-item type=\"button\" (click)=\"setActiveTab('suggestions')\">\n <mat-icon>lightbulb</mat-icon>\n <span>Sugest\u00F5es</span>\n </button>\n <button mat-menu-item type=\"button\" (click)=\"startNewSession()\">\n <mat-icon>add_comment</mat-icon>\n <span>Nova conversa</span>\n </button>\n <button mat-menu-item type=\"button\" (click)=\"refreshSuggestions()\" [disabled]=\"loadingSuggestions\">\n <mat-icon>refresh</mat-icon>\n <span>Atualizar sugest\u00F5es</span>\n </button>\n <button\n mat-menu-item\n type=\"button\"\n (click)=\"restoreDismissedSuggestions()\"\n [disabled]=\"!hasDismissedSuggestions()\"\n >\n <mat-icon>visibility</mat-icon>\n <span>Restaurar sugest\u00F5es ocultas</span>\n </button>\n <button\n mat-menu-item\n type=\"button\"\n class=\"assistant-quick-menu-danger\"\n (click)=\"clearHistory()\"\n [disabled]=\"!historySessions.length\"\n >\n <mat-icon>delete_outline</mat-icon>\n <span>Limpar hist\u00F3rico local</span>\n </button>\n </mat-menu>\n </div>\n\n</ng-template>\n", styles: ["@keyframes assistantPremiumEnter{0%{opacity:0;transform:translate(14px) scale(.99)}to{opacity:1;transform:translate(0) scale(1)}}:host ::ng-deep .ai-assistant-backdrop{background:color-mix(in srgb,var(--md-sys-color-scrim, var(--md-sys-color-shadow, var(--md-sys-color-on-surface))) 42%,transparent);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}::ng-deep .ai-assistant-overlay-pane{max-width:calc(100vw - 24px);max-height:calc(100vh - 24px)}.ai-assistant-panel{box-sizing:border-box;width:min(604px,100vw - 18px);min-height:min(620px,100vh - 18px);max-height:min(820px,100vh - 18px);display:flex;flex-direction:column;overflow:hidden;color:var(--md-sys-color-on-surface);border-left:1px solid color-mix(in srgb,var(--md-sys-color-primary) 24%,var(--md-sys-color-outline-variant));border-top:1px solid color-mix(in srgb,var(--md-sys-color-primary) 18%,var(--md-sys-color-outline-variant));border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-primary) 18%,var(--md-sys-color-outline-variant));box-shadow:0 18px 48px color-mix(in srgb,var(--md-sys-color-shadow, var(--md-sys-color-on-surface)) 42%,transparent),inset 0 1px color-mix(in srgb,var(--md-sys-color-on-surface) 10%,transparent);background:radial-gradient(circle at 14% 8%,color-mix(in srgb,var(--md-sys-color-primary-container) 38%,transparent) 0%,transparent 44%),linear-gradient(165deg,color-mix(in srgb,var(--md-sys-color-surface-container-highest) 88%,var(--md-sys-color-surface)),var(--md-sys-color-surface));animation:assistantPremiumEnter .24s cubic-bezier(.22,1,.36,1)}.assistant-header{position:relative;display:flex;align-items:flex-start;justify-content:space-between;gap:12px;padding:12px 16px 10px;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-primary) 18%,var(--md-sys-color-outline-variant));background:linear-gradient(130deg,color-mix(in srgb,var(--md-sys-color-primary-container) 28%,transparent) 0%,transparent 52%),var(--md-sys-color-surface-container-low)}.assistant-header:after{content:\"\";position:absolute;left:16px;right:16px;bottom:-1px;height:1px;background:linear-gradient(90deg,color-mix(in srgb,var(--md-sys-color-primary) 55%,transparent),transparent);pointer-events:none}.assistant-header .assistant-header__left{min-width:0;display:flex;align-items:flex-start;gap:12px}.assistant-header .magic-icon{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;width:30px;height:30px;font-size:18px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 30%,transparent);box-shadow:0 4px 12px color-mix(in srgb,var(--md-sys-color-primary) 26%,transparent)}.assistant-header .assistant-title-group{min-width:0;display:flex;flex-direction:column;gap:4px}.assistant-header .assistant-title{font-size:15px;font-weight:700;letter-spacing:.01em;overflow-wrap:anywhere}.assistant-header .assistant-subtitle{display:block;font-size:11px;line-height:1.25;color:color-mix(in srgb,var(--md-sys-color-on-surface) 70%,var(--md-sys-color-on-surface-variant));overflow-wrap:anywhere}.assistant-header-chips{display:inline-flex;align-items:center;flex-wrap:wrap;gap:6px}.assistant-header .mode-chip{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:999px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 28%,var(--md-sys-color-outline-variant));background:color-mix(in srgb,var(--md-sys-color-primary-container) 64%,var(--md-sys-color-surface-container));color:color-mix(in srgb,var(--md-sys-color-on-primary-container) 85%,var(--md-sys-color-on-surface));font-size:10px;font-weight:700;letter-spacing:.04em;text-transform:uppercase}.assistant-header .mode-chip:before{content:\"\";width:6px;height:6px;border-radius:999px;background:currentColor;box-shadow:0 0 0 3px color-mix(in srgb,currentColor 16%,transparent)}.assistant-header .mode-chip.mock{border-color:color-mix(in srgb,var(--md-sys-color-error) 34%,var(--md-sys-color-outline-variant));background:color-mix(in srgb,var(--md-sys-color-error-container) 72%,var(--md-sys-color-surface-container));color:color-mix(in srgb,var(--md-sys-color-on-error-container) 85%,var(--md-sys-color-error))}.assistant-header .policy-chip{padding:2px 8px;border-radius:999px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 84%,transparent);background:var(--md-sys-color-surface-container-high);font-size:10px;letter-spacing:.02em;font-weight:600}.assistant-header .policy-chip.strict{border-color:color-mix(in srgb,var(--md-sys-color-primary) 42%,var(--md-sys-color-outline-variant));background:color-mix(in srgb,var(--md-sys-color-primary-container) 56%,var(--md-sys-color-surface-container-high))}.assistant-status{display:flex;align-items:flex-start;gap:10px;padding:10px 16px;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-primary) 18%,var(--md-sys-color-outline-variant));border-radius:0;background:linear-gradient(160deg,color-mix(in srgb,var(--md-sys-color-primary-container) 24%,transparent),transparent 48%),var(--md-sys-color-surface-container-low)}.assistant-status-dot{width:8px;height:8px;margin-top:6px;border-radius:999px;flex:0 0 auto;background:var(--md-sys-color-primary);box-shadow:0 0 0 4px color-mix(in srgb,var(--md-sys-color-primary) 16%,transparent)}.assistant-status.warning .assistant-status-dot{background:var(--md-sys-color-error);box-shadow:0 0 0 4px color-mix(in srgb,var(--md-sys-color-error) 16%,transparent)}.assistant-status.success .assistant-status-dot{background:color-mix(in srgb,var(--md-sys-color-primary) 74%,var(--md-sys-color-tertiary, var(--md-sys-color-primary)))}.assistant-status-content{min-width:0;display:flex;flex-direction:column;gap:2px}.assistant-status-label{display:flex;align-items:center;flex-wrap:wrap;gap:4px;font-size:12px;font-weight:700;line-height:1.35}.assistant-status-detail{font-size:11px;line-height:1.4;color:var(--md-sys-color-on-surface-variant);overflow-wrap:anywhere}.assistant-status-mode{padding:1px 6px;border-radius:999px;background:color-mix(in srgb,var(--md-sys-color-primary-container) 72%,transparent);color:var(--md-sys-color-on-primary-container);font-size:10px;font-weight:700}.assistant-nav{padding:8px 16px 0}.assistant-nav .assistant-tabs{display:flex;align-items:center;gap:4px;border-radius:12px;padding:5px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 24%,var(--md-sys-color-outline-variant));border-color:color-mix(in srgb,var(--md-sys-color-primary) 24%,var(--md-sys-color-outline-variant));background:linear-gradient(155deg,color-mix(in srgb,var(--md-sys-color-primary-container) 14%,transparent),transparent 58%),var(--md-sys-color-surface-container-low)}.assistant-nav .assistant-tab{appearance:none;min-width:0;min-height:30px;border:0;border-radius:8px;padding:0 10px;background:transparent;color:var(--md-sys-color-on-surface-variant);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;flex:1 1 0;font-size:11px;font-weight:700;letter-spacing:.01em}.assistant-nav .assistant-tab.active{background:var(--md-sys-color-surface-container-highest);color:var(--md-sys-color-on-surface);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--md-sys-color-primary) 34%,transparent),0 6px 12px color-mix(in srgb,var(--md-sys-color-primary) 18%,transparent)}.assistant-section,.assistant-card{border-radius:14px;border-color:color-mix(in srgb,var(--md-sys-color-primary) 20%,var(--md-sys-color-outline-variant));background:linear-gradient(160deg,color-mix(in srgb,var(--md-sys-color-primary-container) 16%,transparent),transparent 50%),var(--md-sys-color-surface-container-lowest);box-shadow:0 6px 18px color-mix(in srgb,var(--md-sys-color-shadow, var(--md-sys-color-on-surface)) 12%,transparent),inset 0 1px color-mix(in srgb,var(--md-sys-color-on-surface) 7%,transparent)}.suggestions-hero{margin:2px 0 4px;padding:10px 12px;border-radius:12px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 24%,var(--md-sys-color-outline-variant));background:linear-gradient(120deg,color-mix(in srgb,var(--md-sys-color-primary-container) 34%,transparent) 0%,transparent 52%),var(--md-sys-color-surface-container-low)}.suggestions-hero__label{font-size:10px;letter-spacing:.08em;text-transform:uppercase;font-weight:700;color:var(--md-sys-color-on-surface-variant);opacity:.88}.suggestions-hero__title{margin-top:2px;font-size:13px;font-weight:700;color:var(--md-sys-color-on-surface)}.suggestions-hero__detail{margin-top:4px;font-size:12px;line-height:1.4;color:color-mix(in srgb,var(--md-sys-color-on-surface) 78%,var(--md-sys-color-on-surface-variant))}.suggestions-content .suggestion-item{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:12px;padding:12px;border-radius:12px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 18%,var(--md-sys-color-outline-variant));border-color:color-mix(in srgb,var(--md-sys-color-primary) 18%,var(--md-sys-color-outline-variant));background:linear-gradient(140deg,color-mix(in srgb,var(--md-sys-color-primary-container) 16%,transparent),transparent 56%),var(--md-sys-color-surface-container-lowest);transition:transform .2s cubic-bezier(.25,.8,.25,1),border-color .2s ease,box-shadow .2s ease}.suggestions-list{display:flex;flex-direction:column;gap:10px}.suggestion-copy{min-width:0;display:grid;gap:4px}.suggestion-main{min-width:0;display:flex;align-items:center;flex-wrap:wrap;gap:8px}.suggestion-icon{width:18px;height:18px;font-size:18px;flex:0 0 auto;color:var(--md-sys-color-primary)}.suggestion-label{min-width:0;font-size:13px;font-weight:700;line-height:1.35;overflow-wrap:anywhere}.suggestion-group{padding:2px 6px;border-radius:999px;background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface-variant);font-size:10px;font-weight:700;line-height:1.2}.suggestion-desc{font-size:12px;line-height:1.35;color:var(--md-sys-color-on-surface-variant);overflow-wrap:anywhere}.suggestion-actions{display:inline-flex;align-items:center;justify-content:flex-end;gap:4px}.suggestion-arrow{width:32px;height:32px;display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;color:var(--md-sys-color-on-surface-variant)}.suggestion-action-btn{color:var(--md-sys-color-on-surface-variant)}.suggestion-action-btn--danger,.history-session-tool--danger{color:var(--md-sys-color-error)}.suggestions-content .suggestion-item:hover,.suggestions-content .suggestion-item:focus-visible{border-color:color-mix(in srgb,var(--md-sys-color-primary) 58%,var(--md-sys-color-outline-variant));box-shadow:0 8px 18px color-mix(in srgb,var(--md-sys-color-primary) 18%,transparent),inset 0 0 0 1px color-mix(in srgb,var(--md-sys-color-primary) 28%,transparent);transform:translateY(-2px) scale(1.01)}.assistant-footer{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:8px;padding:10px 16px;border-top-color:color-mix(in srgb,var(--md-sys-color-primary) 20%,var(--md-sys-color-outline-variant));background:linear-gradient(180deg,color-mix(in srgb,var(--md-sys-color-primary-container) 16%,transparent),transparent 56%),var(--md-sys-color-surface-container-low)}.assistant-footer .task-footer{grid-column:1/-1}.composer-leading{color:var(--md-sys-color-primary)}.assistant-footer input{box-sizing:border-box;width:100%;min-width:0;height:34px;border:1px solid;border-radius:8px;padding:0 12px;color:var(--md-sys-color-on-surface);border-color:color-mix(in srgb,var(--md-sys-color-primary) 24%,var(--md-sys-color-outline-variant));background:var(--md-sys-color-surface);box-shadow:inset 0 1px 2px color-mix(in srgb,var(--md-sys-color-shadow, var(--md-sys-color-on-surface)) 12%,transparent)}.send-actions{min-width:36px;display:inline-flex;align-items:center;justify-content:center}.assistant-footer .send-btn{--praxis-icon-button-filled-background: var(--md-sys-color-primary);--praxis-icon-button-filled-foreground: var(--md-sys-color-on-primary)}.assistant-footer .send-btn.ready{color:var(--praxis-icon-button-filled-foreground)}.task-primary-btn{border-radius:12px;box-shadow:0 8px 18px color-mix(in srgb,var(--md-sys-color-primary) 24%,transparent)}@media(max-width:959px){.assistant-header{padding:12px 12px 10px}.assistant-section,.assistant-card{margin:4px 12px 10px}.assistant-header:after{left:12px;right:12px}.assistant-header .assistant-title{font-size:14px}.assistant-header .assistant-subtitle{font-size:10px}.assistant-footer{grid-template-columns:minmax(0,1fr) auto}.composer-leading{display:none}}.assistant-thought{margin-top:0;gap:10px;border-color:color-mix(in srgb,var(--md-sys-color-primary) 26%,var(--md-sys-color-outline-variant));background:linear-gradient(145deg,color-mix(in srgb,var(--md-sys-color-primary-container) 28%,transparent),transparent 58%),var(--md-sys-color-surface-container-low)}.assistant-thought-meta{display:inline-flex;align-items:center;gap:6px;font-size:11px;color:var(--md-sys-color-on-surface-variant)}.assistant-thought-meta mat-icon{width:15px;height:15px;font-size:15px;color:var(--md-sys-color-primary)}.assistant-thought-summary{font-size:13px;line-height:1.45;color:var(--md-sys-color-on-surface)}.assistant-thought-plan{border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 32%,var(--md-sys-color-outline-variant));border-radius:12px;padding:10px;background:var(--md-sys-color-surface-container-lowest);display:flex;flex-direction:column;gap:8px}.assistant-thought-plan-title{font-size:13px;font-weight:700;color:var(--md-sys-color-on-surface)}.assistant-thought-plan-actions{display:grid;grid-template-columns:repeat(auto-fit,minmax(0,1fr));gap:8px}.assistant-thought-plan-actions .mdc-button{min-width:0}.assistant-thought-plan-hint{font-size:11px;color:var(--md-sys-color-on-surface-variant);line-height:1.35}.assistant-thought-checklist{display:flex;flex-direction:column;gap:5px}.assistant-thought-checklist-item{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--md-sys-color-on-surface-variant)}.assistant-thought-checklist-item mat-icon{width:14px;height:14px;font-size:14px}.assistant-thought-shimmer{display:flex;flex-direction:column;gap:8px;margin-top:4px}.assistant-thought-shimmer .shimmer-line{height:12px;border-radius:4px;position:relative;overflow:hidden;background:var(--md-sys-color-surface-container-highest)}.assistant-thought-shimmer .shimmer-line:after{content:\"\";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--md-sys-color-primary) 8%,transparent),transparent);animation:assistantShimmerEffect 1.5s infinite}.assistant-thought-shimmer .shimmer-line-1{width:85%}.assistant-thought-shimmer .shimmer-line-2{width:92%}.assistant-thought-shimmer .shimmer-line-3{width:64%}@keyframes assistantShimmerEffect{to{transform:translate(100%)}}.assistant-flow{grid-template-columns:1fr;gap:6px}.flow-step{display:flex;align-items:flex-start;gap:8px;text-align:left;padding:7px 8px;border-radius:10px}.flow-step-index{width:18px;height:18px;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;font-size:10px;font-weight:700;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-highest);color:var(--md-sys-color-on-surface);flex:0 0 auto}.flow-step-content{min-width:0;display:flex;flex-direction:column;gap:1px}.flow-step-label{font-size:11px;font-weight:700;color:var(--md-sys-color-on-surface)}.flow-step-detail{font-size:11px;color:var(--md-sys-color-on-surface-variant);line-height:1.3}.flow-step.active .flow-step-index{border-color:color-mix(in srgb,var(--md-sys-color-primary) 60%,var(--md-sys-color-outline-variant));background:color-mix(in srgb,var(--md-sys-color-primary-container) 85%,var(--md-sys-color-surface-container-highest));color:var(--md-sys-color-on-primary-container)}.flow-step.done .flow-step-index{border-color:transparent;background:color-mix(in srgb,var(--md-sys-color-primary) 18%,var(--md-sys-color-surface-container-highest))}.task-timeline{margin-top:4px;display:grid;gap:6px}.task-timeline-item{display:flex;align-items:flex-start;gap:8px;border:1px solid var(--md-sys-color-outline-variant);border-radius:10px;padding:6px 8px;background:var(--md-sys-color-surface-container-low);opacity:.76}.task-timeline-item.active{opacity:1;border-color:color-mix(in srgb,var(--md-sys-color-primary) 40%,var(--md-sys-color-outline-variant));background:color-mix(in srgb,var(--md-sys-color-primary-container) 34%,var(--md-sys-color-surface-container-low))}.task-timeline-item.done{opacity:.9;border-color:color-mix(in srgb,var(--md-sys-color-primary) 24%,var(--md-sys-color-outline-variant))}.task-timeline-dot{width:18px;height:18px;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;font-size:10px;font-weight:700;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-highest);color:var(--md-sys-color-on-surface);flex:0 0 auto}.task-timeline-copy{min-width:0;display:flex;flex-direction:column;gap:1px}.task-timeline-title{font-size:11px;font-weight:700;color:var(--md-sys-color-on-surface)}.task-timeline-detail{font-size:11px;line-height:1.3;color:var(--md-sys-color-on-surface-variant)}.clarification-decision-head{display:inline-flex;align-items:center;width:100%;gap:6px;padding:8px 12px 0;box-sizing:border-box}.clarification-decision-index{width:18px;height:18px;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;font-size:10px;font-weight:700;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 35%,var(--md-sys-color-outline-variant));color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary-container) 68%,transparent)}.clarification-decision-type{font-size:10px;letter-spacing:.08em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant);opacity:.92}.clarification-decision-state{font-size:10px;font-weight:700;color:var(--md-sys-color-primary)}.clarification-option{border-color:color-mix(in srgb,var(--md-sys-color-primary) 20%,var(--md-sys-color-outline-variant));background:linear-gradient(145deg,color-mix(in srgb,var(--md-sys-color-primary-container) 16%,transparent),transparent 55%),var(--md-sys-color-surface-container-low)}.clarification-option.selected{border-color:color-mix(in srgb,var(--md-sys-color-primary) 56%,var(--md-sys-color-outline-variant));background:linear-gradient(145deg,color-mix(in srgb,var(--md-sys-color-primary-container) 44%,transparent),transparent 62%),var(--md-sys-color-surface-container);box-shadow:0 8px 16px color-mix(in srgb,var(--md-sys-color-primary) 18%,transparent)}.clarification-options-block{overflow:visible;padding-right:4px}@media(max-width:959px){.assistant-thought-plan-actions{grid-template-columns:1fr}}.ai-assistant-panel{width:min(604px,100vw - 18px)}.assistant-section,.assistant-card{margin:0;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 20%,var(--md-sys-color-outline-variant))}.assistant-section{min-height:0;padding:14px 16px;overflow:visible}.assistant-card{min-height:0;padding:14px 16px 16px;overflow:visible}.suggestions-area,.assistant-history,.loading-suggestions{overflow-y:auto;overflow-x:hidden}.section-header{min-width:0;display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:10px}.section-title{min-width:0;font-size:14px;font-weight:700;line-height:1.35;overflow-wrap:anywhere}.suggestions-actions{flex:0 0 auto;display:inline-flex;align-items:center}.review-area,.error-area,.success-area,.clarification-area{padding:0;overflow-y:auto;overflow-x:hidden;scrollbar-gutter:auto}.review-trust{margin:2px 0 4px}.trust-chip{max-width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.warnings-area,.review-summary,.review-diff,.apply-details,.clarification-options-block,.clarification-manual-toggle{width:100%;max-width:100%;min-width:0}.review-diff{padding:12px 14px}.review-diff-full{padding:10px;overflow-x:auto}.review-diff-block{min-width:0}.review-diff-block pre{overflow-wrap:anywhere;word-break:break-word}.clarification-options-block{padding:4px 2px 10px}.clarification-option{line-height:normal}:host ::ng-deep .clarification-option .mdc-button__label{line-height:1.35!important}.clarification-plain-label{padding:6px 12px 12px;font-size:14px;line-height:1.35}.clarification-manual-toggle{margin-top:10px;padding:10px 2px 0;flex-wrap:wrap;row-gap:6px}.suggestions-content .suggestion-actions{gap:6px}.suggestions-content .suggestion-arrow,.suggestions-content .suggestion-action-btn mat-icon,.suggestions-content .suggestion-arrow mat-icon{display:inline-flex;align-items:center;justify-content:center}:host ::ng-deep .assistant-quick-menu-panel{min-width:244px;max-width:min(90vw,320px);border-radius:14px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 26%,var(--md-sys-color-outline-variant));background:var(--md-sys-color-surface-container-high);box-shadow:0 12px 28px color-mix(in srgb,var(--md-sys-color-shadow, var(--md-sys-color-on-surface)) 32%,transparent),inset 0 1px color-mix(in srgb,var(--md-sys-color-on-surface) 6%,transparent);overflow:hidden;padding:6px}:host ::ng-deep .assistant-quick-menu-panel .mat-mdc-menu-item{min-height:36px;border-radius:10px;color:var(--md-sys-color-on-surface);font-size:12px;font-weight:500;margin:1px 0}:host ::ng-deep .assistant-quick-menu-panel .mat-mdc-menu-item .mat-icon{color:color-mix(in srgb,var(--md-sys-color-on-surface) 82%,var(--md-sys-color-on-surface-variant))}:host ::ng-deep .assistant-quick-menu-panel .mat-mdc-menu-item:hover:not([disabled]){background:color-mix(in srgb,var(--md-sys-color-primary-container) 45%,transparent)}:host ::ng-deep .assistant-quick-menu-panel .mat-mdc-menu-item:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:-2px}:host ::ng-deep .assistant-quick-menu-panel .assistant-quick-menu-danger{color:var(--md-sys-color-error)}:host ::ng-deep .assistant-quick-menu-panel .assistant-quick-menu-danger .mat-icon{color:var(--md-sys-color-error)}@media(max-width:959px){::ng-deep .ai-assistant-overlay-pane{top:12px!important;left:12px!important;width:calc(100vw - 24px)!important;height:calc(100vh - 24px)!important;max-width:calc(100vw - 24px);max-height:calc(100vh - 24px);transform:none!important}.ai-assistant-panel{width:calc(100vw - 48px);min-height:min(620px,100vh - 48px);max-height:calc(100vh - 48px)}.assistant-section,.assistant-card{margin:0}.assistant-card,.assistant-section{padding:12px}}.ai-trigger-btn{color:var(--md-sys-color-primary);opacity:1}.assistant-tab:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.assistant-close-btn{color:var(--md-sys-color-on-surface-variant)}.assistant-body{padding:12px 16px;overflow:hidden;min-height:0;flex:1;display:flex;flex-direction:column;gap:12px}.assistant-body>*{min-height:0}@media(max-width:959px){.assistant-nav{padding:8px 12px 0}.assistant-body,.assistant-footer{padding:10px 12px}.suggestions-content .suggestion-item{grid-template-columns:1fr;align-items:start}.suggestion-actions{justify-content:flex-start}}\n"] }]
|
|
7761
8004
|
}], propDecorators: { adapter: [{
|
|
7762
8005
|
type: Input,
|
|
7763
8006
|
args: [{ required: true }]
|
|
@@ -7778,129 +8021,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
7778
8021
|
args: ['inputEl']
|
|
7779
8022
|
}] } });
|
|
7780
8023
|
|
|
7781
|
-
class PraxisBrowserSpeechTranscriptionError extends Error {
|
|
7782
|
-
code;
|
|
7783
|
-
constructor(code, message) {
|
|
7784
|
-
super(message);
|
|
7785
|
-
this.code = code;
|
|
7786
|
-
this.name = 'PraxisBrowserSpeechTranscriptionError';
|
|
7787
|
-
}
|
|
7788
|
-
}
|
|
7789
|
-
class PraxisBrowserSpeechTranscriptionService {
|
|
7790
|
-
activeRecognition = null;
|
|
7791
|
-
isSupported() {
|
|
7792
|
-
return this.resolveCtor() !== null;
|
|
7793
|
-
}
|
|
7794
|
-
transcribe(options = {}) {
|
|
7795
|
-
const RecognitionCtor = this.resolveCtor();
|
|
7796
|
-
if (!RecognitionCtor) {
|
|
7797
|
-
return Promise.reject(new PraxisBrowserSpeechTranscriptionError('unsupported', 'Browser speech recognition is not supported.'));
|
|
7798
|
-
}
|
|
7799
|
-
this.cancel();
|
|
7800
|
-
const recognition = new RecognitionCtor();
|
|
7801
|
-
recognition.lang = options.lang?.trim() || this.resolveNavigatorLanguage();
|
|
7802
|
-
recognition.continuous = false;
|
|
7803
|
-
recognition.interimResults = false;
|
|
7804
|
-
recognition.maxAlternatives = 1;
|
|
7805
|
-
this.activeRecognition = recognition;
|
|
7806
|
-
return new Promise((resolve, reject) => {
|
|
7807
|
-
let transcript = '';
|
|
7808
|
-
let failed = false;
|
|
7809
|
-
const cleanup = () => {
|
|
7810
|
-
if (this.activeRecognition === recognition) {
|
|
7811
|
-
this.activeRecognition = null;
|
|
7812
|
-
}
|
|
7813
|
-
recognition.onresult = null;
|
|
7814
|
-
recognition.onerror = null;
|
|
7815
|
-
recognition.onend = null;
|
|
7816
|
-
};
|
|
7817
|
-
recognition.onresult = (event) => {
|
|
7818
|
-
transcript = this.extractTranscript(event).trim();
|
|
7819
|
-
};
|
|
7820
|
-
recognition.onerror = (event) => {
|
|
7821
|
-
failed = true;
|
|
7822
|
-
cleanup();
|
|
7823
|
-
reject(this.toTranscriptionError(event));
|
|
7824
|
-
};
|
|
7825
|
-
recognition.onend = () => {
|
|
7826
|
-
cleanup();
|
|
7827
|
-
if (failed) {
|
|
7828
|
-
return;
|
|
7829
|
-
}
|
|
7830
|
-
if (!transcript) {
|
|
7831
|
-
reject(new PraxisBrowserSpeechTranscriptionError('no-speech', 'No speech was recognized.'));
|
|
7832
|
-
return;
|
|
7833
|
-
}
|
|
7834
|
-
resolve({
|
|
7835
|
-
text: transcript,
|
|
7836
|
-
language: recognition.lang,
|
|
7837
|
-
});
|
|
7838
|
-
};
|
|
7839
|
-
try {
|
|
7840
|
-
recognition.start();
|
|
7841
|
-
}
|
|
7842
|
-
catch (error) {
|
|
7843
|
-
cleanup();
|
|
7844
|
-
reject(new PraxisBrowserSpeechTranscriptionError('error', error instanceof Error ? error.message : 'Failed to start browser speech recognition.'));
|
|
7845
|
-
}
|
|
7846
|
-
});
|
|
7847
|
-
}
|
|
7848
|
-
stop() {
|
|
7849
|
-
this.activeRecognition?.stop();
|
|
7850
|
-
}
|
|
7851
|
-
cancel() {
|
|
7852
|
-
this.activeRecognition?.abort();
|
|
7853
|
-
this.activeRecognition = null;
|
|
7854
|
-
}
|
|
7855
|
-
extractTranscript(event) {
|
|
7856
|
-
const segments = [];
|
|
7857
|
-
for (let resultIndex = 0; resultIndex < event.results.length; resultIndex++) {
|
|
7858
|
-
const result = event.results[resultIndex] ?? event.results.item(resultIndex);
|
|
7859
|
-
if (!result?.length) {
|
|
7860
|
-
continue;
|
|
7861
|
-
}
|
|
7862
|
-
const alternative = result[0] ?? result.item(0);
|
|
7863
|
-
const text = alternative?.transcript?.trim();
|
|
7864
|
-
if (text) {
|
|
7865
|
-
segments.push(text);
|
|
7866
|
-
}
|
|
7867
|
-
}
|
|
7868
|
-
return segments.join(' ');
|
|
7869
|
-
}
|
|
7870
|
-
toTranscriptionError(event) {
|
|
7871
|
-
const error = (event.error || '').toLowerCase();
|
|
7872
|
-
if (error === 'not-allowed' || error === 'service-not-allowed') {
|
|
7873
|
-
return new PraxisBrowserSpeechTranscriptionError('permission-denied', event.message || 'Browser microphone permission was denied.');
|
|
7874
|
-
}
|
|
7875
|
-
if (error === 'no-speech') {
|
|
7876
|
-
return new PraxisBrowserSpeechTranscriptionError('no-speech', event.message || 'No speech was recognized.');
|
|
7877
|
-
}
|
|
7878
|
-
if (error === 'aborted') {
|
|
7879
|
-
return new PraxisBrowserSpeechTranscriptionError('aborted', event.message || 'Browser speech recognition was aborted.');
|
|
7880
|
-
}
|
|
7881
|
-
return new PraxisBrowserSpeechTranscriptionError('error', event.message || 'Browser speech recognition failed.');
|
|
7882
|
-
}
|
|
7883
|
-
resolveCtor() {
|
|
7884
|
-
if (typeof window === 'undefined') {
|
|
7885
|
-
return null;
|
|
7886
|
-
}
|
|
7887
|
-
const speechWindow = window;
|
|
7888
|
-
return speechWindow.SpeechRecognition ?? speechWindow.webkitSpeechRecognition ?? null;
|
|
7889
|
-
}
|
|
7890
|
-
resolveNavigatorLanguage() {
|
|
7891
|
-
if (typeof navigator !== 'undefined' && navigator.language?.trim()) {
|
|
7892
|
-
return navigator.language.trim();
|
|
7893
|
-
}
|
|
7894
|
-
return 'pt-BR';
|
|
7895
|
-
}
|
|
7896
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisBrowserSpeechTranscriptionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
7897
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisBrowserSpeechTranscriptionService, providedIn: 'root' });
|
|
7898
|
-
}
|
|
7899
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisBrowserSpeechTranscriptionService, decorators: [{
|
|
7900
|
-
type: Injectable,
|
|
7901
|
-
args: [{ providedIn: 'root' }]
|
|
7902
|
-
}] });
|
|
7903
|
-
|
|
7904
8024
|
const PRAXIS_ASSISTANT_VOICE_INPUT_MODE = new InjectionToken('PRAXIS_ASSISTANT_VOICE_INPUT_MODE', {
|
|
7905
8025
|
providedIn: 'root',
|
|
7906
8026
|
factory: () => 'disabled',
|
|
@@ -7948,6 +8068,7 @@ const DEFAULT_LABELS = {
|
|
|
7948
8068
|
voiceStop: 'Parar ditado',
|
|
7949
8069
|
voiceListening: 'Ouvindo...',
|
|
7950
8070
|
voiceUnsupported: 'Ditado pelo navegador indisponível',
|
|
8071
|
+
voiceFailed: 'Não foi possível transcrever o áudio. Tente novamente.',
|
|
7951
8072
|
voicePermissionDenied: 'Permissão do microfone negada pelo navegador.',
|
|
7952
8073
|
voiceNoSpeech: 'Nenhuma fala reconhecida.',
|
|
7953
8074
|
modeConfig: 'Configuração',
|
|
@@ -8026,6 +8147,7 @@ class PraxisAiAssistantShellComponent {
|
|
|
8026
8147
|
cdr = inject(ChangeDetectorRef);
|
|
8027
8148
|
injector = inject(Injector);
|
|
8028
8149
|
browserSpeech = inject(PraxisBrowserSpeechTranscriptionService);
|
|
8150
|
+
governedSpeech = inject(PraxisGovernedAudioTranscriptionService);
|
|
8029
8151
|
currentPrompt = '';
|
|
8030
8152
|
resolvedLabels = DEFAULT_LABELS;
|
|
8031
8153
|
voiceCaptureState = 'idle';
|
|
@@ -8044,7 +8166,10 @@ class PraxisAiAssistantShellComponent {
|
|
|
8044
8166
|
onWindowPointerUp = (event) => this.finishPointerSession(event);
|
|
8045
8167
|
ngAfterViewInit() {
|
|
8046
8168
|
queueMicrotask(() => {
|
|
8047
|
-
if (this.destroyed
|
|
8169
|
+
if (this.destroyed)
|
|
8170
|
+
return;
|
|
8171
|
+
this.resizePromptToContent();
|
|
8172
|
+
if (this.busy)
|
|
8048
8173
|
return;
|
|
8049
8174
|
this.promptInput?.nativeElement.focus({ preventScroll: true });
|
|
8050
8175
|
});
|
|
@@ -8052,6 +8177,7 @@ class PraxisAiAssistantShellComponent {
|
|
|
8052
8177
|
ngOnChanges(changes) {
|
|
8053
8178
|
if (changes['prompt']) {
|
|
8054
8179
|
this.currentPrompt = this.prompt ?? '';
|
|
8180
|
+
this.schedulePromptResize();
|
|
8055
8181
|
}
|
|
8056
8182
|
if (changes['labels']) {
|
|
8057
8183
|
this.resolvedLabels = {
|
|
@@ -8068,7 +8194,7 @@ class PraxisAiAssistantShellComponent {
|
|
|
8068
8194
|
if (changes['attachments']) {
|
|
8069
8195
|
this.revokeDetachedPastedPreviewUrls();
|
|
8070
8196
|
}
|
|
8071
|
-
if (changes['voiceInputMode'] &&
|
|
8197
|
+
if (changes['voiceInputMode'] && !changes['voiceInputMode'].firstChange) {
|
|
8072
8198
|
this.cancelVoiceCapture();
|
|
8073
8199
|
}
|
|
8074
8200
|
if (changes['state'] || changes['busy']) {
|
|
@@ -8081,6 +8207,7 @@ class PraxisAiAssistantShellComponent {
|
|
|
8081
8207
|
this.stopProcessingTimer();
|
|
8082
8208
|
this.detachPointerListeners();
|
|
8083
8209
|
this.browserSpeech.cancel();
|
|
8210
|
+
this.governedSpeech.cancel();
|
|
8084
8211
|
this.revokeAllOwnedPreviewUrls();
|
|
8085
8212
|
}
|
|
8086
8213
|
onViewportResize() {
|
|
@@ -8093,6 +8220,14 @@ class PraxisAiAssistantShellComponent {
|
|
|
8093
8220
|
this.currentPrompt = value;
|
|
8094
8221
|
this.promptChange.emit(value);
|
|
8095
8222
|
}
|
|
8223
|
+
resizePromptToContent() {
|
|
8224
|
+
const prompt = this.promptInput?.nativeElement;
|
|
8225
|
+
if (!prompt)
|
|
8226
|
+
return;
|
|
8227
|
+
prompt.style.height = 'auto';
|
|
8228
|
+
prompt.style.height = `${Math.min(prompt.scrollHeight, 160)}px`;
|
|
8229
|
+
prompt.style.overflowY = prompt.scrollHeight > 160 ? 'auto' : 'hidden';
|
|
8230
|
+
}
|
|
8096
8231
|
onSubmit() {
|
|
8097
8232
|
const value = this.currentPrompt.trim();
|
|
8098
8233
|
if (!value || this.busy || !this.canSubmit)
|
|
@@ -8123,7 +8258,7 @@ class PraxisAiAssistantShellComponent {
|
|
|
8123
8258
|
if (this.isVoiceInputBusy()) {
|
|
8124
8259
|
this.voiceCaptureState = 'stopping';
|
|
8125
8260
|
this.voiceFeedbackText = this.getVoiceLabel('voiceListening');
|
|
8126
|
-
this.
|
|
8261
|
+
this.activeVoiceService().stop();
|
|
8127
8262
|
return;
|
|
8128
8263
|
}
|
|
8129
8264
|
if (!this.canUseBrowserSpeech()) {
|
|
@@ -8135,7 +8270,7 @@ class PraxisAiAssistantShellComponent {
|
|
|
8135
8270
|
this.voiceFeedbackText = this.getVoiceLabel('voiceListening');
|
|
8136
8271
|
this.cdr.markForCheck();
|
|
8137
8272
|
const captureSequence = ++this.voiceCaptureSequence;
|
|
8138
|
-
void this.
|
|
8273
|
+
void this.activeVoiceService().transcribe({ lang: this.voiceLanguage }).then((result) => {
|
|
8139
8274
|
if (!this.isCurrentVoiceCapture(captureSequence)) {
|
|
8140
8275
|
return;
|
|
8141
8276
|
}
|
|
@@ -8159,7 +8294,7 @@ class PraxisAiAssistantShellComponent {
|
|
|
8159
8294
|
});
|
|
8160
8295
|
}
|
|
8161
8296
|
shouldShowVoiceInput() {
|
|
8162
|
-
return this.voiceInputMode
|
|
8297
|
+
return this.voiceInputMode !== 'disabled';
|
|
8163
8298
|
}
|
|
8164
8299
|
isVoiceInputDisabled() {
|
|
8165
8300
|
return (this.busy && !this.isVoiceInputBusy()) || (!this.isVoiceInputBusy() && !this.canUseBrowserSpeech());
|
|
@@ -8179,19 +8314,25 @@ class PraxisAiAssistantShellComponent {
|
|
|
8179
8314
|
return !!this.voiceFeedbackText.trim();
|
|
8180
8315
|
}
|
|
8181
8316
|
canUseBrowserSpeech() {
|
|
8182
|
-
return this.voiceInputMode === 'browser-speech'
|
|
8317
|
+
return this.voiceInputMode === 'browser-speech'
|
|
8318
|
+
? this.browserSpeech.isSupported()
|
|
8319
|
+
: this.voiceInputMode === 'governed-transcription' && this.governedSpeech.isSupported();
|
|
8183
8320
|
}
|
|
8184
8321
|
cancelVoiceCapture() {
|
|
8185
8322
|
this.voiceCaptureSequence++;
|
|
8186
8323
|
this.browserSpeech.cancel();
|
|
8324
|
+
this.governedSpeech.cancel();
|
|
8187
8325
|
this.voiceCaptureState = 'idle';
|
|
8188
8326
|
this.voiceFeedbackText = '';
|
|
8189
8327
|
}
|
|
8190
8328
|
isCurrentVoiceCapture(captureSequence) {
|
|
8191
8329
|
return !this.destroyed
|
|
8192
|
-
&& this.voiceInputMode
|
|
8330
|
+
&& this.voiceInputMode !== 'disabled'
|
|
8193
8331
|
&& captureSequence === this.voiceCaptureSequence;
|
|
8194
8332
|
}
|
|
8333
|
+
activeVoiceService() {
|
|
8334
|
+
return this.voiceInputMode === 'governed-transcription' ? this.governedSpeech : this.browserSpeech;
|
|
8335
|
+
}
|
|
8195
8336
|
applyVoiceTranscript(text) {
|
|
8196
8337
|
const transcript = text.trim();
|
|
8197
8338
|
if (!transcript) {
|
|
@@ -8201,6 +8342,14 @@ class PraxisAiAssistantShellComponent {
|
|
|
8201
8342
|
const next = current ? `${current}\n${transcript}` : transcript;
|
|
8202
8343
|
this.currentPrompt = next;
|
|
8203
8344
|
this.promptChange.emit(next);
|
|
8345
|
+
this.schedulePromptResize();
|
|
8346
|
+
}
|
|
8347
|
+
schedulePromptResize() {
|
|
8348
|
+
queueMicrotask(() => {
|
|
8349
|
+
if (!this.destroyed) {
|
|
8350
|
+
this.resizePromptToContent();
|
|
8351
|
+
}
|
|
8352
|
+
});
|
|
8204
8353
|
}
|
|
8205
8354
|
resolveVoiceErrorText(error) {
|
|
8206
8355
|
if (error instanceof PraxisBrowserSpeechTranscriptionError) {
|
|
@@ -8215,10 +8364,10 @@ class PraxisAiAssistantShellComponent {
|
|
|
8215
8364
|
return '';
|
|
8216
8365
|
case 'error':
|
|
8217
8366
|
default:
|
|
8218
|
-
return this.getVoiceLabel('
|
|
8367
|
+
return this.getVoiceLabel('voiceFailed');
|
|
8219
8368
|
}
|
|
8220
8369
|
}
|
|
8221
|
-
return this.getVoiceLabel('
|
|
8370
|
+
return this.getVoiceLabel('voiceFailed');
|
|
8222
8371
|
}
|
|
8223
8372
|
getVoiceLabel(key) {
|
|
8224
8373
|
return this.resolvedLabels[key] ?? DEFAULT_LABELS[key] ?? '';
|
|
@@ -8251,13 +8400,21 @@ class PraxisAiAssistantShellComponent {
|
|
|
8251
8400
|
renderMessageText(text) {
|
|
8252
8401
|
const lines = (text ?? '').replace(/\r\n?/g, '\n').split('\n');
|
|
8253
8402
|
const html = [];
|
|
8254
|
-
let
|
|
8403
|
+
let listType = null;
|
|
8255
8404
|
const closeList = () => {
|
|
8256
|
-
if (
|
|
8257
|
-
html.push(
|
|
8258
|
-
|
|
8405
|
+
if (listType) {
|
|
8406
|
+
html.push(`</${listType}>`);
|
|
8407
|
+
listType = null;
|
|
8259
8408
|
}
|
|
8260
8409
|
};
|
|
8410
|
+
const appendListItem = (type, value) => {
|
|
8411
|
+
if (listType !== type) {
|
|
8412
|
+
closeList();
|
|
8413
|
+
html.push(`<${type}>`);
|
|
8414
|
+
listType = type;
|
|
8415
|
+
}
|
|
8416
|
+
html.push(`<li>${this.renderInlineMarkdown(value)}</li>`);
|
|
8417
|
+
};
|
|
8261
8418
|
for (const rawLine of lines) {
|
|
8262
8419
|
const line = rawLine.trim();
|
|
8263
8420
|
if (!line) {
|
|
@@ -8273,11 +8430,12 @@ class PraxisAiAssistantShellComponent {
|
|
|
8273
8430
|
}
|
|
8274
8431
|
const bullet = line.match(/^[-*]\s+(.+)$/);
|
|
8275
8432
|
if (bullet) {
|
|
8276
|
-
|
|
8277
|
-
|
|
8278
|
-
|
|
8279
|
-
|
|
8280
|
-
|
|
8433
|
+
appendListItem('ul', bullet[1]);
|
|
8434
|
+
continue;
|
|
8435
|
+
}
|
|
8436
|
+
const ordered = line.match(/^\d+[.)]\s+(.+)$/);
|
|
8437
|
+
if (ordered) {
|
|
8438
|
+
appendListItem('ol', ordered[1]);
|
|
8281
8439
|
continue;
|
|
8282
8440
|
}
|
|
8283
8441
|
closeList();
|
|
@@ -8730,6 +8888,8 @@ class PraxisAiAssistantShellComponent {
|
|
|
8730
8888
|
].filter(Boolean).join('\n');
|
|
8731
8889
|
}
|
|
8732
8890
|
isRichQuickReply(reply) {
|
|
8891
|
+
if (this.isConversationQuickActionQuickReply(reply))
|
|
8892
|
+
return false;
|
|
8733
8893
|
return Boolean(this.getQuickReplyDescription(reply)
|
|
8734
8894
|
|| this.getQuickReplyPresentationItems(reply).length
|
|
8735
8895
|
|| this.getQuickReplyContextChips(reply).length);
|
|
@@ -9096,6 +9256,9 @@ class PraxisAiAssistantShellComponent {
|
|
|
9096
9256
|
|| this.quickReplyPresentation(reply)?.description?.trim());
|
|
9097
9257
|
return kind === 'clarification-option' && hasActionPresentation;
|
|
9098
9258
|
}
|
|
9259
|
+
isConversationQuickActionQuickReply(reply) {
|
|
9260
|
+
return this.quickReplyPresentationKind(reply) === 'quick-action';
|
|
9261
|
+
}
|
|
9099
9262
|
quickReplyPresentation(reply) {
|
|
9100
9263
|
const presentation = reply.presentation;
|
|
9101
9264
|
return presentation && typeof presentation === 'object' && !Array.isArray(presentation)
|
|
@@ -9653,7 +9816,7 @@ class PraxisAiAssistantShellComponent {
|
|
|
9653
9816
|
this.ownedPreviewUrls.delete(previewUrl);
|
|
9654
9817
|
}
|
|
9655
9818
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisAiAssistantShellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
9656
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PraxisAiAssistantShellComponent, isStandalone: true, selector: "praxis-ai-assistant-shell", inputs: { labels: "labels", mode: "mode", state: "state", contextItems: "contextItems", attachments: "attachments", messages: "messages", quickReplies: "quickReplies", recommendedIntents: "recommendedIntents", prompt: "prompt", statusText: "statusText", errorText: "errorText", testIdPrefix: "testIdPrefix", panelTestId: "panelTestId", submitTestId: "submitTestId", applyTestId: "applyTestId", primaryAction: "primaryAction", secondaryActions: "secondaryActions", governanceActions: "governanceActions", busy: "busy", canSubmit: "canSubmit", canApply: "canApply", submitOnEnter: "submitOnEnter", showAttachAction: "showAttachAction", enablePastedAttachments: "enablePastedAttachments", enableFileAttachments: "enableFileAttachments", attachmentAccept: "attachmentAccept", attachmentMultiple: "attachmentMultiple", voiceInputMode: "voiceInputMode", voiceLanguage: "voiceLanguage", draggable: "draggable", resizable: "resizable", minWidth: "minWidth", minHeight: "minHeight", margin: "margin", layout: "layout" }, outputs: { promptChange: "promptChange", submitPrompt: "submitPrompt", apply: "apply", retryTurn: "retryTurn", cancelTurn: "cancelTurn", shellAction: "shellAction", close: "close", attach: "attach", attachmentsPasted: "attachmentsPasted", attachmentsSelected: "attachmentsSelected", removeAttachment: "removeAttachment", messageAction: "messageAction", editMessage: "editMessage", resendMessage: "resendMessage", quickReply: "quickReply", recommendedIntent: "recommendedIntent", layoutChange: "layoutChange" }, host: { listeners: { "window:resize": "onViewportResize()" } }, providers: [PraxisBrowserSpeechTranscriptionService], viewQueries: [{ propertyName: "panel", first: true, predicate: ["panel"], descendants: true, static: true }, { propertyName: "conversation", first: true, predicate: ["conversation"], descendants: true }, { propertyName: "promptInput", first: true, predicate: ["promptInput"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<section\n #panel\n class=\"praxis-ai-assistant-shell\"\n role=\"dialog\"\n [attr.aria-label]=\"resolvedLabels.title\"\n [attr.aria-busy]=\"busy ? 'true' : null\"\n [style.left.px]=\"currentLayout.left\"\n [style.top.px]=\"currentLayout.top\"\n [style.width.px]=\"currentLayout.width\"\n [style.height.px]=\"currentLayout.height\"\n [attr.data-testid]=\"panelTestId || testIdPrefix\"\n [attr.data-mode]=\"mode\"\n [attr.data-state]=\"state\"\n >\n <header\n class=\"praxis-ai-assistant-shell__header\"\n [attr.data-testid]=\"testIdPrefix + '-drag-handle'\"\n [attr.aria-label]=\"resolvedLabels.dragHandleAria\"\n (pointerdown)=\"startDrag($event)\"\n >\n <div class=\"praxis-ai-assistant-shell__identity\" aria-hidden=\"true\">\n <mat-icon>auto_awesome</mat-icon>\n </div>\n <div class=\"praxis-ai-assistant-shell__title-group\">\n <div class=\"praxis-ai-assistant-shell__title-row\">\n <strong>{{ resolvedLabels.title }}</strong>\n <div class=\"praxis-ai-assistant-shell__badges\" aria-hidden=\"true\">\n <span class=\"praxis-ai-assistant-shell__badge praxis-ai-assistant-shell__badge--context\">\n {{ getModeLabel() }}\n </span>\n <span\n class=\"praxis-ai-assistant-shell__badge praxis-ai-assistant-shell__badge--state\"\n [class.praxis-ai-assistant-shell__badge--error]=\"state === 'error'\"\n >\n <span class=\"praxis-ai-assistant-shell__state-dot\" aria-hidden=\"true\"></span>\n {{ getStateLabel() }}\n </span>\n </div>\n </div>\n @if (resolvedLabels.subtitle) {\n <p>{{ resolvedLabels.subtitle }}</p>\n }\n </div>\n <div class=\"praxis-ai-assistant-shell__header-actions\">\n <button\n mat-icon-button\n type=\"button\"\n [matTooltip]=\"resolvedLabels.close\"\n [attr.aria-label]=\"resolvedLabels.close\"\n (pointerdown)=\"$event.stopPropagation()\"\n (click)=\"close.emit()\"\n [attr.data-testid]=\"testIdPrefix + '-close'\"\n >\n <mat-icon>{{ getCloseIcon() }}</mat-icon>\n </button>\n </div>\n </header>\n\n <div class=\"praxis-ai-assistant-shell__body\">\n @if (contextItems.length) {\n <div\n class=\"praxis-ai-assistant-shell__context\"\n [attr.aria-label]=\"resolvedLabels.contextAria\"\n [attr.data-testid]=\"testIdPrefix + '-context'\"\n >\n @for (item of contextItems; track trackContextItem($index, item)) {\n <span\n class=\"praxis-ai-assistant-shell__context-item\"\n [attr.data-testid]=\"testIdPrefix + '-context-' + item.id\"\n >\n @if (item.icon) {\n <mat-icon aria-hidden=\"true\">{{ item.icon }}</mat-icon>\n }\n <span class=\"praxis-ai-assistant-shell__context-label\">{{ item.label }}</span>\n @if (item.value) {\n <span class=\"praxis-ai-assistant-shell__context-value\">{{ getContextItemValue(item) }}</span>\n }\n </span>\n }\n </div>\n }\n\n @if (shouldShowRecommendedIntents()) {\n <section\n class=\"praxis-ai-assistant-shell__recommended\"\n [attr.aria-label]=\"resolvedLabels.recommendedIntentsAria\"\n [attr.data-testid]=\"testIdPrefix + '-recommended-intents'\"\n >\n <div class=\"praxis-ai-assistant-shell__recommended-header\">\n <mat-icon aria-hidden=\"true\">auto_awesome</mat-icon>\n <span>{{ resolvedLabels.recommendedIntentsTitle }}</span>\n </div>\n <div class=\"praxis-ai-assistant-shell__recommended-list\">\n @for (intent of recommendedIntents; track trackRecommendedIntent($index, intent)) {\n <button\n type=\"button\"\n class=\"praxis-ai-assistant-shell__recommended-intent\"\n [ngClass]=\"'praxis-ai-assistant-shell__recommended-intent--tone-' + getRecommendedIntentTone(intent)\"\n [attr.data-testid]=\"testIdPrefix + '-recommended-intent-' + intent.id\"\n [attr.aria-label]=\"getRecommendedIntentAriaLabel(intent)\"\n [disabled]=\"isRecommendedIntentDisabled(intent)\"\n (click)=\"onRecommendedIntent(intent)\"\n >\n <span class=\"praxis-ai-assistant-shell__recommended-icon\" aria-hidden=\"true\">\n <mat-icon>{{ getRecommendedIntentIcon(intent) }}</mat-icon>\n </span>\n <span class=\"praxis-ai-assistant-shell__recommended-copy\">\n <span class=\"praxis-ai-assistant-shell__recommended-title-row\">\n <span class=\"praxis-ai-assistant-shell__recommended-title\">{{ intent.label }}</span>\n @if (getRecommendedIntentGroupLabel(intent)) {\n <span class=\"praxis-ai-assistant-shell__recommended-group\">\n {{ getRecommendedIntentGroupLabel(intent) }}\n </span>\n }\n </span>\n @if (getRecommendedIntentDescription(intent)) {\n <span class=\"praxis-ai-assistant-shell__recommended-description\">\n {{ getRecommendedIntentDescription(intent) }}\n </span>\n }\n <span class=\"praxis-ai-assistant-shell__recommended-cta\">\n @if (intent.requiresConfirmation && !intent.disabledReason) {\n <span>{{ resolvedLabels.recommendedIntentRequiresConfirmation }}</span>\n }\n <span>{{ getRecommendedIntentCtaLabel(intent) }}</span>\n <mat-icon aria-hidden=\"true\">arrow_forward</mat-icon>\n </span>\n </span>\n </button>\n }\n </div>\n </section>\n }\n\n <div\n #conversation\n class=\"praxis-ai-assistant-shell__conversation\"\n [attr.data-testid]=\"testIdPrefix + '-conversation'\"\n [attr.aria-label]=\"resolvedLabels.conversationAria\"\n >\n @if (!messages.length) {\n <article\n class=\"praxis-ai-assistant-shell__message praxis-ai-assistant-shell__message--assistant\"\n [attr.data-testid]=\"testIdPrefix + '-message-assistant-empty'\"\n >\n {{ resolvedLabels.emptyConversation }}\n </article>\n }\n @for (message of messages; track trackMessage($index, message)) {\n <article\n class=\"praxis-ai-assistant-shell__message\"\n [class.praxis-ai-assistant-shell__message--user]=\"message.role === 'user'\"\n [class.praxis-ai-assistant-shell__message--assistant]=\"message.role === 'assistant'\"\n [class.praxis-ai-assistant-shell__message--status]=\"message.role === 'status'\"\n [class.praxis-ai-assistant-shell__message--error]=\"message.role === 'error'\"\n [attr.data-testid]=\"testIdPrefix + '-message-' + message.role\"\n >\n <div\n class=\"praxis-ai-assistant-shell__message-content\"\n >\n @if (hasStructuredAssistantContent(message)) {\n <div class=\"praxis-ai-assistant-shell__assistant-content\">\n @for (block of getAssistantContentBlocks(message); track trackAssistantContentBlock($index, block)) {\n @switch (getAssistantContentBlockType(block)) {\n @case ('paragraph') {\n <section class=\"praxis-ai-assistant-shell__assistant-block praxis-ai-assistant-shell__assistant-block--summary\">\n <span class=\"praxis-ai-assistant-shell__assistant-block-icon\" aria-hidden=\"true\">\n <mat-icon>lightbulb</mat-icon>\n </span>\n <div\n class=\"praxis-ai-assistant-shell__assistant-block-copy\"\n [innerHTML]=\"renderMessageText(getAssistantContentBlockText(block))\"\n ></div>\n </section>\n }\n @case ('resource-list') {\n <section class=\"praxis-ai-assistant-shell__assistant-block\">\n <div class=\"praxis-ai-assistant-shell__assistant-block-heading\">\n <mat-icon aria-hidden=\"true\">database</mat-icon>\n <span>{{ getAssistantContentBlockTitle(block, 'Fontes confirmadas') }}</span>\n </div>\n <div class=\"praxis-ai-assistant-shell__assistant-resources\">\n @for (resource of getAssistantContentResources(block); track trackAssistantContentResource($index, resource)) {\n <article class=\"praxis-ai-assistant-shell__assistant-resource\">\n <div class=\"praxis-ai-assistant-shell__assistant-resource-head\">\n <strong>{{ resource.label }}</strong>\n @if (getAssistantContentResourceMeta(resource).length) {\n <span class=\"praxis-ai-assistant-shell__assistant-resource-meta\">\n @for (item of getAssistantContentResourceMeta(resource); track trackAssistantContentValue($index, item)) {\n <span>{{ item }}</span>\n }\n </span>\n }\n </div>\n @if (resource.description) {\n <p>{{ resource.description }}</p>\n }\n @if (resource.fields.length) {\n <div class=\"praxis-ai-assistant-shell__assistant-field-list\" aria-label=\"Campos dispon\u00EDveis\">\n @for (field of resource.fields; track trackAssistantContentField($index, field)) {\n <span\n class=\"praxis-ai-assistant-shell__assistant-field\"\n [matTooltip]=\"field.description || field.name\"\n >\n {{ field.label }}\n </span>\n }\n </div>\n }\n @if (resource.evidence.length) {\n <div class=\"praxis-ai-assistant-shell__assistant-evidence\" aria-label=\"Evid\u00EAncias\">\n @for (item of resource.evidence; track trackAssistantContentValue($index, item)) {\n <span>\n <mat-icon aria-hidden=\"true\">verified</mat-icon>\n {{ item }}\n </span>\n }\n </div>\n }\n </article>\n }\n </div>\n </section>\n }\n @case ('recommendation') {\n <section class=\"praxis-ai-assistant-shell__assistant-block praxis-ai-assistant-shell__assistant-block--recommendation\">\n <span class=\"praxis-ai-assistant-shell__assistant-block-icon\" aria-hidden=\"true\">\n <mat-icon>recommend</mat-icon>\n </span>\n <div class=\"praxis-ai-assistant-shell__assistant-block-copy\">\n <strong>{{ getAssistantContentBlockTitle(block, 'Recomenda\u00E7\u00E3o') }}</strong>\n <p>{{ getAssistantContentBlockText(block) }}</p>\n </div>\n </section>\n }\n }\n }\n </div>\n } @else {\n <div [innerHTML]=\"renderMessageText(message.text)\"></div>\n }\n </div>\n @if (message.actions?.length || message.editable || message.resendable) {\n <div\n class=\"praxis-ai-assistant-shell__message-actions\"\n >\n @if (message.editable) {\n <button\n mat-icon-button\n type=\"button\"\n class=\"praxis-ai-assistant-shell__message-action praxis-ai-assistant-shell__message-action--icon\"\n [disabled]=\"busy\"\n [matTooltip]=\"resolvedLabels.editMessage\"\n [attr.aria-label]=\"resolvedLabels.editMessage\"\n [attr.data-testid]=\"testIdPrefix + '-message-edit-' + message.id\"\n (click)=\"onMessageAction(message, { id: 'edit', label: resolvedLabels.editMessage, kind: 'edit' })\"\n >\n <mat-icon aria-hidden=\"true\">edit</mat-icon>\n </button>\n }\n @if (message.resendable) {\n <button\n mat-icon-button\n type=\"button\"\n class=\"praxis-ai-assistant-shell__message-action praxis-ai-assistant-shell__message-action--icon\"\n [disabled]=\"busy\"\n [matTooltip]=\"resolvedLabels.resendMessage\"\n [attr.aria-label]=\"resolvedLabels.resendMessage\"\n [attr.data-testid]=\"testIdPrefix + '-message-resend-' + message.id\"\n (click)=\"onMessageAction(message, { id: 'resend', label: resolvedLabels.resendMessage, kind: 'resend' })\"\n >\n <mat-icon aria-hidden=\"true\">replay</mat-icon>\n </button>\n }\n @for (action of message.actions || []; track trackMessageAction($index, action)) {\n @if (isMessageActionIconOnly(action)) {\n <button\n mat-icon-button\n type=\"button\"\n class=\"praxis-ai-assistant-shell__message-action praxis-ai-assistant-shell__message-action--icon\"\n [disabled]=\"busy || action.disabled\"\n [matTooltip]=\"getMessageActionLabel(action)\"\n [attr.aria-label]=\"getMessageActionLabel(action)\"\n [attr.data-testid]=\"testIdPrefix + '-message-action-' + message.id + '-' + action.id\"\n (click)=\"onMessageAction(message, action)\"\n >\n <mat-icon aria-hidden=\"true\">{{ getMessageActionIcon(action) }}</mat-icon>\n </button>\n } @else {\n <button\n mat-button\n type=\"button\"\n class=\"praxis-ai-assistant-shell__message-action\"\n [disabled]=\"busy || action.disabled\"\n [attr.aria-label]=\"getMessageActionLabel(action)\"\n [attr.data-testid]=\"testIdPrefix + '-message-action-' + message.id + '-' + action.id\"\n (click)=\"onMessageAction(message, action)\"\n >\n {{ action.label }}\n </button>\n }\n }\n </div>\n }\n @if (canSendMessageFeedback(message)) {\n <div class=\"praxis-ai-assistant-shell__message-feedback\">\n <button\n mat-icon-button\n type=\"button\"\n class=\"praxis-ai-assistant-shell__message-feedback-action\"\n [disabled]=\"busy\"\n [matTooltip]=\"resolvedLabels.feedbackPositive\"\n [attr.aria-label]=\"resolvedLabels.feedbackPositive\"\n [attr.data-testid]=\"testIdPrefix + '-message-feedback-positive-' + message.id\"\n (click)=\"sendMessageFeedback(message, 'positive')\"\n >\n <mat-icon aria-hidden=\"true\">thumb_up</mat-icon>\n </button>\n <button\n mat-icon-button\n type=\"button\"\n class=\"praxis-ai-assistant-shell__message-feedback-action\"\n [disabled]=\"busy\"\n [matTooltip]=\"resolvedLabels.feedbackNegative\"\n [attr.aria-label]=\"resolvedLabels.feedbackNegative\"\n [attr.data-testid]=\"testIdPrefix + '-message-feedback-negative-' + message.id\"\n (click)=\"sendMessageFeedback(message, 'negative')\"\n >\n <mat-icon aria-hidden=\"true\">thumb_down</mat-icon>\n </button>\n </div>\n } @else if (isMessageFeedbackSubmitted(message)) {\n <div\n class=\"praxis-ai-assistant-shell__message-feedback-submitted\"\n [attr.data-testid]=\"testIdPrefix + '-message-feedback-submitted-' + message.id\"\n >\n <mat-icon aria-hidden=\"true\">check</mat-icon>\n <span>{{ resolvedLabels.feedbackSubmitted }}</span>\n </div>\n }\n </article>\n }\n </div>\n\n @if (attachments.length) {\n <div\n class=\"praxis-ai-assistant-shell__attachments\"\n [attr.aria-label]=\"resolvedLabels.attachmentsAria\"\n [attr.data-testid]=\"testIdPrefix + '-attachments'\"\n >\n @for (attachment of attachments; track trackAttachment($index, attachment)) {\n <div\n class=\"praxis-ai-assistant-shell__attachment\"\n [class.praxis-ai-assistant-shell__attachment--error]=\"attachment.status === 'error'\"\n [attr.data-testid]=\"testIdPrefix + '-attachment-' + attachment.id\"\n >\n @if (attachment.previewUrl && attachment.kind === 'image') {\n <img\n class=\"praxis-ai-assistant-shell__attachment-preview\"\n [src]=\"attachment.previewUrl\"\n [alt]=\"attachment.name\"\n >\n }\n <span class=\"praxis-ai-assistant-shell__attachment-name\">{{ attachment.name }}</span>\n <span class=\"praxis-ai-assistant-shell__attachment-kind\">{{ attachment.kind }}</span>\n <button\n mat-icon-button\n type=\"button\"\n [disabled]=\"busy\"\n [matTooltip]=\"resolvedLabels.removeAttachment\"\n [attr.aria-label]=\"resolvedLabels.removeAttachment + ': ' + attachment.name\"\n [attr.data-testid]=\"testIdPrefix + '-attachment-remove-' + attachment.id\"\n (click)=\"onRemoveAttachment(attachment)\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </div>\n }\n </div>\n }\n\n @if (quickReplies.length) {\n <div\n class=\"praxis-ai-assistant-shell__quick-replies\"\n [class.praxis-ai-assistant-shell__quick-replies--inline]=\"shouldUseInlineQuickReplies()\"\n [attr.data-testid]=\"testIdPrefix + '-quick-replies'\"\n [attr.aria-label]=\"resolvedLabels.quickRepliesAria\"\n >\n @for (reply of quickReplies; track trackQuickReply($index, reply)) {\n <button\n mat-stroked-button\n type=\"button\"\n class=\"praxis-ai-assistant-shell__quick-reply\"\n [class.praxis-ai-assistant-shell__quick-reply--compact]=\"!isRichQuickReply(reply)\"\n [class.praxis-ai-assistant-shell__quick-reply--guided-action]=\"isGuidedActionQuickReply(reply)\"\n [class.praxis-ai-assistant-shell__quick-reply--contextual-action]=\"isContextualPreviewActionQuickReply(reply)\"\n [class.praxis-ai-assistant-shell__quick-reply--source-review]=\"isSourceReviewQuickReply(reply)\"\n [ngClass]=\"'praxis-ai-assistant-shell__quick-reply--tone-' + getQuickReplyTone(reply)\"\n [attr.data-testid]=\"testIdPrefix + '-quick-reply-' + (reply.id || reply.kind)\"\n [attr.aria-label]=\"getQuickReplyAriaLabel(reply)\"\n [disabled]=\"busy\"\n (click)=\"onQuickReply(reply)\"\n >\n <span class=\"praxis-ai-assistant-shell__quick-reply-ambient\" aria-hidden=\"true\"></span>\n <span class=\"praxis-ai-assistant-shell__quick-reply-icon-frame\" aria-hidden=\"true\">\n <mat-icon\n class=\"praxis-ai-assistant-shell__quick-reply-icon\"\n >\n {{ getQuickReplyIcon(reply) }}\n </mat-icon>\n </span>\n <span class=\"praxis-ai-assistant-shell__quick-reply-copy\">\n <span class=\"praxis-ai-assistant-shell__quick-reply-header\">\n <span class=\"praxis-ai-assistant-shell__quick-reply-heading\">\n <span class=\"praxis-ai-assistant-shell__quick-reply-label\">{{ getQuickReplyLabel(reply) }}</span>\n @if (getQuickReplyDescription(reply)) {\n <span\n class=\"praxis-ai-assistant-shell__quick-reply-description\"\n >\n {{ getQuickReplyDescription(reply) }}\n </span>\n }\n </span>\n <span class=\"praxis-ai-assistant-shell__quick-reply-actions\">\n <span class=\"praxis-ai-assistant-shell__quick-reply-badge\">\n {{ getQuickReplyCategoryLabel(reply) }}\n </span>\n @if (getQuickReplyTechnicalDetails(reply)) {\n <mat-icon\n class=\"praxis-ai-assistant-shell__quick-reply-details\"\n [matTooltip]=\"getQuickReplyTechnicalDetails(reply)\"\n [attr.aria-label]=\"resolvedLabels.quickReplyDetails\"\n >\n info\n </mat-icon>\n }\n </span>\n </span>\n @if (getQuickReplyContextChips(reply).length) {\n <span\n class=\"praxis-ai-assistant-shell__quick-reply-context\"\n >\n @for (chip of getQuickReplyContextChips(reply); track chip.ariaLabel + ':' + chip.value) {\n <span\n class=\"praxis-ai-assistant-shell__quick-reply-context-chip\"\n [attr.aria-label]=\"chip.ariaLabel\"\n >\n <mat-icon aria-hidden=\"true\">{{ chip.icon }}</mat-icon>\n <span>{{ chip.value }}</span>\n </span>\n }\n </span>\n }\n @if (getQuickReplyPresentationItems(reply).length) {\n <span\n class=\"praxis-ai-assistant-shell__quick-reply-insights\"\n >\n @for (item of getQuickReplyPresentationItems(reply); track item.key) {\n <span\n class=\"praxis-ai-assistant-shell__quick-reply-insight\"\n >\n <mat-icon aria-hidden=\"true\">{{ item.icon }}</mat-icon>\n <span class=\"praxis-ai-assistant-shell__quick-reply-insight-copy\">\n <span class=\"praxis-ai-assistant-shell__quick-reply-insight-label\">\n {{ item.label }}\n </span>\n <span class=\"praxis-ai-assistant-shell__quick-reply-insight-value\">\n {{ item.value }}\n </span>\n </span>\n </span>\n }\n </span>\n }\n <span class=\"praxis-ai-assistant-shell__quick-reply-cta\">\n {{ getQuickReplyCtaLabel(reply) }}\n <mat-icon aria-hidden=\"true\">arrow_forward</mat-icon>\n </span>\n </span>\n </button>\n }\n </div>\n }\n @if (shouldShowStatusText()) {\n <p\n class=\"praxis-ai-assistant-shell__status\"\n [attr.data-testid]=\"testIdPrefix + '-status'\"\n >\n {{ getAuxiliaryStatusText() }}\n </p>\n }\n @if (shouldShowErrorText()) {\n <p\n class=\"praxis-ai-assistant-shell__error\"\n [attr.data-testid]=\"testIdPrefix + '-error'\"\n >\n {{ errorText }}\n </p>\n }\n </div>\n\n <footer class=\"praxis-ai-assistant-shell__footer\">\n <label class=\"praxis-ai-assistant-shell__label\" for=\"praxis-ai-assistant-shell-prompt\">\n {{ resolvedLabels.prompt }}\n </label>\n <div class=\"praxis-ai-assistant-shell__composer\">\n <textarea\n #promptInput\n id=\"praxis-ai-assistant-shell-prompt\"\n class=\"praxis-ai-assistant-shell__prompt\"\n [attr.data-testid]=\"testIdPrefix + '-prompt'\"\n [placeholder]=\"resolvedLabels.promptPlaceholder\"\n [ngModel]=\"currentPrompt\"\n [disabled]=\"busy\"\n (ngModelChange)=\"onPromptInput($event)\"\n (keydown)=\"onPromptKeydown($event)\"\n (paste)=\"onPromptPaste($event)\"\n ></textarea>\n <div class=\"praxis-ai-assistant-shell__composer-actions\">\n @if (shouldShowVoiceInput()) {\n <button\n mat-icon-button\n type=\"button\"\n class=\"praxis-ai-assistant-shell__voice-action\"\n [class.praxis-ai-assistant-shell__voice-action--active]=\"isVoiceInputBusy()\"\n [class.praxis-ai-assistant-shell__voice-action--error]=\"voiceCaptureState === 'error' || voiceCaptureState === 'unsupported'\"\n [disabled]=\"isVoiceInputDisabled()\"\n [matTooltip]=\"getVoiceActionLabel()\"\n [attr.aria-label]=\"getVoiceActionLabel()\"\n [attr.aria-pressed]=\"isVoiceInputBusy() ? 'true' : 'false'\"\n [attr.data-testid]=\"testIdPrefix + '-voice'\"\n (click)=\"onVoiceInputClick()\"\n >\n <mat-icon aria-hidden=\"true\">{{ isVoiceInputBusy() ? 'stop_circle' : 'mic' }}</mat-icon>\n </button>\n }\n @if (showAttachAction) {\n <input\n #attachmentInput\n type=\"file\"\n hidden\n [attr.accept]=\"attachmentAccept || null\"\n [attr.multiple]=\"attachmentMultiple ? '' : null\"\n [attr.data-testid]=\"testIdPrefix + '-attachment-input'\"\n (change)=\"onAttachmentFilesSelected($event)\"\n >\n <button\n mat-stroked-button\n type=\"button\"\n [disabled]=\"busy\"\n (click)=\"onAttachClick(attachmentInput)\"\n [attr.data-testid]=\"testIdPrefix + '-attach'\"\n >\n <mat-icon>attach_file</mat-icon>\n {{ resolvedLabels.attach }}\n </button>\n }\n <button\n mat-flat-button\n color=\"primary\"\n type=\"button\"\n class=\"praxis-ai-assistant-shell__action praxis-ai-assistant-shell__action--primary\"\n [class.praxis-ai-assistant-shell__action--icon-only]=\"getPrimaryAction().iconOnly\"\n [matTooltip]=\"getPrimaryActionTooltip(getPrimaryAction())\"\n [ngClass]=\"'praxis-ai-assistant-shell__action--tone-' + getShellActionTone(getPrimaryAction())\"\n [disabled]=\"isShellActionDisabled(getPrimaryAction())\"\n (click)=\"onShellAction(getPrimaryAction())\"\n [attr.data-testid]=\"getPrimaryAction().testId || (submitTestId || (testIdPrefix + '-submit'))\"\n [attr.aria-label]=\"getPrimaryAction().ariaLabel || getPrimaryAction().label\"\n >\n @if (getPrimaryAction().icon) {\n <mat-icon aria-hidden=\"true\">{{ getPrimaryAction().icon }}</mat-icon>\n }\n @if (!getPrimaryAction().iconOnly) {\n <span>{{ getPrimaryAction().label }}</span>\n }\n </button>\n @for (action of getSecondaryActions(); track trackShellAction($index, action)) {\n <button\n mat-button\n type=\"button\"\n class=\"praxis-ai-assistant-shell__action praxis-ai-assistant-shell__action--secondary\"\n [ngClass]=\"'praxis-ai-assistant-shell__action--tone-' + getShellActionTone(action)\"\n [disabled]=\"isShellActionDisabled(action)\"\n (click)=\"onShellAction(action)\"\n [attr.data-testid]=\"action.testId || (testIdPrefix + '-action-' + action.id)\"\n [attr.aria-label]=\"action.ariaLabel || action.label\"\n >\n @if (action.icon) {\n <mat-icon aria-hidden=\"true\">{{ action.icon }}</mat-icon>\n }\n {{ action.label }}\n </button>\n }\n @if (busy) {\n <mat-spinner diameter=\"20\" [attr.data-testid]=\"testIdPrefix + '-spinner'\"></mat-spinner>\n }\n </div>\n @if (shouldShowVoiceFeedback()) {\n <p\n class=\"praxis-ai-assistant-shell__voice-status\"\n aria-live=\"polite\"\n [attr.data-testid]=\"testIdPrefix + '-voice-status'\"\n >\n {{ voiceFeedbackText }}\n </p>\n }\n </div>\n </footer>\n\n @if (resizable) {\n @for (direction of resizeHandles; track trackResizeHandle($index, direction)) {\n <span\n class=\"praxis-ai-assistant-shell__resize-handle praxis-ai-assistant-shell__resize-handle--{{ direction }}\"\n [attr.data-testid]=\"direction === 'se' ? testIdPrefix + '-resize-handle' : testIdPrefix + '-resize-handle-' + direction\"\n aria-hidden=\"true\"\n role=\"presentation\"\n (pointerdown)=\"startResize(direction, $event)\"\n ></span>\n }\n }\n</section>\n", styles: [":host{display:block;position:fixed;inset:0;z-index:var(--praxis-ai-assistant-shell-z-index, 1200);pointer-events:none}.praxis-ai-assistant-shell{--praxis-ai-assistant-shell-shadow-color: var(--md-sys-color-shadow);--praxis-ai-assistant-shell-highlight-color: var(--md-sys-color-on-surface);--praxis-ai-assistant-shell-tone-analytics: var(--md-sys-color-primary);--praxis-ai-assistant-shell-tone-resource: var(--md-sys-color-tertiary);--praxis-ai-assistant-shell-tone-success: var(--md-sys-color-tertiary);--praxis-ai-assistant-shell-tone-warning: var(--md-sys-color-secondary);--praxis-ai-assistant-shell-tone-danger: var(--md-sys-color-error);--praxis-ai-assistant-shell-tone-neutral: var(--md-sys-color-outline);position:fixed;box-sizing:border-box;min-width:0;min-height:0;display:flex;flex-direction:column;overflow:hidden;color:var(--md-sys-color-on-surface);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 70%,transparent);border-radius:8px;background:var(--md-sys-color-surface);box-shadow:0 24px 60px color-mix(in srgb,var(--praxis-ai-assistant-shell-shadow-color) 40%,transparent);pointer-events:auto;z-index:var(--praxis-ai-assistant-shell-z-index, 1200);container-type:inline-size}.praxis-ai-assistant-shell__header{flex:0 0 auto;display:flex;align-items:flex-start;gap:9px;padding:10px 10px 9px;border-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 72%,transparent);background:var(--md-sys-color-surface-container)}.praxis-ai-assistant-shell__header{justify-content:flex-start;border-bottom:1px solid;cursor:move;touch-action:none}.praxis-ai-assistant-shell__identity{flex:0 0 auto;display:grid;place-items:center;width:30px;height:30px;border-radius:8px;background:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary);box-shadow:0 6px 16px color-mix(in srgb,var(--md-sys-color-primary) 22%,transparent)}.praxis-ai-assistant-shell__identity mat-icon{width:18px;height:18px;font-size:18px}.praxis-ai-assistant-shell__title-group{min-width:0;flex:1 1 auto;display:grid;gap:4px}.praxis-ai-assistant-shell__title-row{min-width:0;display:flex;align-items:center;gap:8px}.praxis-ai-assistant-shell__badges{flex:0 0 auto;display:flex;align-items:center;justify-content:flex-end;gap:4px;min-width:0;flex-wrap:wrap}.praxis-ai-assistant-shell__badge{display:inline-flex;align-items:center;gap:5px;min-height:20px;max-width:120px;padding:2px 7px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 80%,transparent);border-radius:8px;color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container-high);font-size:11px;line-height:1.2;overflow-wrap:anywhere}.praxis-ai-assistant-shell__badge--context{color:var(--md-sys-color-on-surface);background:color-mix(in srgb,var(--md-sys-color-primary) 9%,var(--md-sys-color-surface-container-high))}.praxis-ai-assistant-shell__badge--state{border-color:transparent;background:transparent;color:var(--md-sys-color-on-surface-variant);padding-inline:3px}.praxis-ai-assistant-shell__badge--error{color:var(--md-sys-color-error);border-color:color-mix(in srgb,var(--md-sys-color-error) 60%,transparent)}.praxis-ai-assistant-shell__state-dot{flex:0 0 auto;width:6px;height:6px;border-radius:999px;background:var(--md-sys-color-primary);box-shadow:0 0 0 2px color-mix(in srgb,var(--md-sys-color-primary) 16%,transparent)}.praxis-ai-assistant-shell__badge--error .praxis-ai-assistant-shell__state-dot{background:var(--md-sys-color-error);box-shadow:0 0 0 2px color-mix(in srgb,var(--md-sys-color-error) 16%,transparent)}.praxis-ai-assistant-shell__title-group strong,.praxis-ai-assistant-shell__title-group p{min-width:0;margin:0;overflow-wrap:anywhere}.praxis-ai-assistant-shell__title-group strong{flex:1 1 auto;font-size:13px;line-height:1.2}.praxis-ai-assistant-shell__title-group p{color:var(--md-sys-color-on-surface-variant);font-size:11.5px;line-height:1.3}.praxis-ai-assistant-shell__header-actions{flex:0 0 auto;display:flex;align-items:center;gap:2px;margin-top:-3px}.praxis-ai-assistant-shell__header-actions button{display:inline-grid;place-items:center;width:34px;height:34px;padding:0;color:var(--md-sys-color-on-surface-variant);line-height:1;opacity:.78}.praxis-ai-assistant-shell__header-actions button:hover,.praxis-ai-assistant-shell__header-actions button:focus-visible{opacity:1}.praxis-ai-assistant-shell__header-actions mat-icon{display:block;width:18px;height:18px;font-size:18px;line-height:18px}.praxis-ai-assistant-shell__body{min-height:0;flex:1 1 auto;display:flex;flex-direction:column;gap:10px;padding:12px 12px 10px;overflow:auto;background:linear-gradient(180deg,var(--md-sys-color-surface-container-low),var(--md-sys-color-surface))}.praxis-ai-assistant-shell__context,.praxis-ai-assistant-shell__attachments{flex:0 0 auto;display:flex;align-items:center;gap:8px;overflow-x:auto;scrollbar-width:thin}.praxis-ai-assistant-shell__context-item{flex:0 0 auto;display:inline-flex;align-items:center;gap:5px;max-width:240px;padding:5px 8px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 70%,transparent);border-radius:8px;background:var(--md-sys-color-surface-container-high);font-size:12px;line-height:1.25}.praxis-ai-assistant-shell__context-item mat-icon{width:16px;height:16px;font-size:16px}.praxis-ai-assistant-shell__context-label,.praxis-ai-assistant-shell__context-value{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.praxis-ai-assistant-shell__context-label{color:var(--md-sys-color-on-surface)}.praxis-ai-assistant-shell__context-value{color:var(--md-sys-color-on-surface-variant)}.praxis-ai-assistant-shell__label{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.praxis-ai-assistant-shell__prompt{box-sizing:border-box;width:100%;min-height:46px;max-height:96px;resize:none;border:0;padding:10px 12px 8px;color:var(--md-sys-color-on-surface);background:transparent;font:inherit;line-height:1.45;outline:none}.praxis-ai-assistant-shell__recommended{flex:0 0 auto;display:grid;gap:8px}.praxis-ai-assistant-shell__recommended-header{display:inline-flex;align-items:center;gap:6px;color:var(--md-sys-color-on-surface-variant);font-size:12px;font-weight:600;line-height:1.25}.praxis-ai-assistant-shell__recommended-header mat-icon{width:16px;height:16px;color:var(--md-sys-color-primary);font-size:16px;line-height:16px}.praxis-ai-assistant-shell__recommended-list{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,210px),1fr));gap:8px}.praxis-ai-assistant-shell__recommended-intent{--praxis-ai-assistant-shell-recommended-accent: var(--praxis-ai-assistant-shell-tone-neutral);appearance:none;border:1px solid color-mix(in srgb,var(--praxis-ai-assistant-shell-recommended-accent) 34%,transparent);border-radius:8px;background:linear-gradient(180deg,color-mix(in srgb,var(--praxis-ai-assistant-shell-recommended-accent) 8%,transparent),transparent),var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface);cursor:pointer;display:flex;gap:9px;min-width:0;min-height:86px;padding:10px;text-align:left;transition:border-color .16s ease,box-shadow .16s ease,background-color .16s ease}.praxis-ai-assistant-shell__recommended-intent:hover:not(:disabled),.praxis-ai-assistant-shell__recommended-intent:focus-visible{border-color:color-mix(in srgb,var(--praxis-ai-assistant-shell-recommended-accent) 68%,transparent);box-shadow:0 0 0 3px color-mix(in srgb,var(--praxis-ai-assistant-shell-recommended-accent) 15%,transparent);outline:none}.praxis-ai-assistant-shell__recommended-intent:disabled{cursor:default;opacity:.62}.praxis-ai-assistant-shell__recommended-icon{flex:0 0 auto;display:grid;place-items:center;width:30px;height:30px;border:1px solid color-mix(in srgb,var(--praxis-ai-assistant-shell-recommended-accent) 28%,transparent);border-radius:8px;background:color-mix(in srgb,var(--praxis-ai-assistant-shell-recommended-accent) 12%,transparent);color:var(--praxis-ai-assistant-shell-recommended-accent)}.praxis-ai-assistant-shell__recommended-icon mat-icon{width:18px;height:18px;font-size:18px;line-height:18px}.praxis-ai-assistant-shell__recommended-copy{min-width:0;display:grid;gap:5px}.praxis-ai-assistant-shell__recommended-title-row{min-width:0;display:flex;align-items:flex-start;justify-content:space-between;gap:8px}.praxis-ai-assistant-shell__recommended-title,.praxis-ai-assistant-shell__recommended-description,.praxis-ai-assistant-shell__recommended-group{min-width:0;overflow-wrap:anywhere}.praxis-ai-assistant-shell__recommended-title{color:var(--md-sys-color-on-surface);font-size:13px;font-weight:700;line-height:1.25}.praxis-ai-assistant-shell__recommended-group{flex:0 1 auto;max-width:44%;border-radius:8px;padding:2px 6px;background:color-mix(in srgb,var(--praxis-ai-assistant-shell-recommended-accent) 10%,transparent);color:color-mix(in srgb,var(--praxis-ai-assistant-shell-recommended-accent) 84%,var(--praxis-ai-assistant-shell-highlight-color));font-size:10.5px;font-weight:700;line-height:1.25}.praxis-ai-assistant-shell__recommended-description{color:var(--md-sys-color-on-surface-variant);font-size:12px;line-height:1.35}.praxis-ai-assistant-shell__recommended-cta{display:inline-flex;align-items:center;gap:5px;flex-wrap:wrap;color:color-mix(in srgb,var(--praxis-ai-assistant-shell-recommended-accent) 84%,var(--praxis-ai-assistant-shell-highlight-color));font-size:11.5px;font-weight:700;line-height:1.25}.praxis-ai-assistant-shell__recommended-cta mat-icon{width:15px;height:15px;font-size:15px;line-height:15px}.praxis-ai-assistant-shell__recommended-intent--tone-analytics{--praxis-ai-assistant-shell-recommended-accent: var(--praxis-ai-assistant-shell-tone-analytics)}.praxis-ai-assistant-shell__recommended-intent--tone-resource{--praxis-ai-assistant-shell-recommended-accent: var(--praxis-ai-assistant-shell-tone-resource)}.praxis-ai-assistant-shell__recommended-intent--tone-success{--praxis-ai-assistant-shell-recommended-accent: var(--praxis-ai-assistant-shell-tone-success)}.praxis-ai-assistant-shell__recommended-intent--tone-warning{--praxis-ai-assistant-shell-recommended-accent: var(--praxis-ai-assistant-shell-tone-warning)}.praxis-ai-assistant-shell__recommended-intent--tone-danger{--praxis-ai-assistant-shell-recommended-accent: var(--praxis-ai-assistant-shell-tone-danger)}.praxis-ai-assistant-shell__recommended-intent--tone-neutral{--praxis-ai-assistant-shell-recommended-accent: var(--praxis-ai-assistant-shell-tone-neutral)}.praxis-ai-assistant-shell__conversation{min-height:0;flex:1 1 auto;display:flex;flex-direction:column;gap:8px;overflow:auto;padding:2px}.praxis-ai-assistant-shell__message{max-width:86%;align-self:flex-start;padding:9px 11px;border-radius:8px;background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface);font-size:13px;line-height:1.35;overflow-wrap:anywhere}.praxis-ai-assistant-shell__message-content{white-space:normal}.praxis-ai-assistant-shell__message-content :where(p,ul,h3,h4,h5){margin:0}.praxis-ai-assistant-shell__message-content :where(p,ul,h3,h4,h5)+:where(p,ul,h3,h4,h5){margin-top:8px}.praxis-ai-assistant-shell__message-content ul{padding-left:18px}.praxis-ai-assistant-shell__message-content li+li{margin-top:4px}.praxis-ai-assistant-shell__message-content code{padding:1px 4px;border-radius:4px;background:color-mix(in srgb,var(--md-sys-color-on-surface) 10%,transparent);font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:.94em}.praxis-ai-assistant-shell__assistant-content{display:grid;gap:8px}.praxis-ai-assistant-shell__assistant-block{display:grid;gap:8px;min-width:0}.praxis-ai-assistant-shell__assistant-block--summary,.praxis-ai-assistant-shell__assistant-block--recommendation{grid-template-columns:auto minmax(0,1fr);align-items:flex-start;padding:9px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 22%,transparent);border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-primary) 7%,transparent)}.praxis-ai-assistant-shell__assistant-block--recommendation{border-color:color-mix(in srgb,var(--praxis-ai-assistant-shell-tone-success) 26%,transparent);background:color-mix(in srgb,var(--praxis-ai-assistant-shell-tone-success) 8%,transparent)}.praxis-ai-assistant-shell__assistant-block-icon{display:grid;place-items:center;width:24px;height:24px;border-radius:8px;color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 14%,transparent)}.praxis-ai-assistant-shell__assistant-block--recommendation .praxis-ai-assistant-shell__assistant-block-icon{color:var(--praxis-ai-assistant-shell-tone-success);background:color-mix(in srgb,var(--praxis-ai-assistant-shell-tone-success) 14%,transparent)}.praxis-ai-assistant-shell__assistant-block-icon mat-icon{width:16px;height:16px;font-size:16px;line-height:16px}.praxis-ai-assistant-shell__assistant-block-copy{min-width:0}.praxis-ai-assistant-shell__assistant-block-copy strong{display:block;margin-bottom:3px}.praxis-ai-assistant-shell__assistant-block-heading{display:inline-flex;align-items:center;gap:6px;color:var(--md-sys-color-on-surface);font-size:12px;font-weight:700}.praxis-ai-assistant-shell__assistant-block-heading mat-icon{width:16px;height:16px;color:var(--md-sys-color-primary);font-size:16px}.praxis-ai-assistant-shell__assistant-resources{display:grid;gap:7px}.praxis-ai-assistant-shell__assistant-resource{display:grid;gap:7px;min-width:0;padding:9px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 76%,transparent);border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-surface-container-highest) 74%,transparent)}.praxis-ai-assistant-shell__assistant-resource-head{display:flex;align-items:flex-start;justify-content:space-between;gap:8px;min-width:0}.praxis-ai-assistant-shell__assistant-resource-head strong{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.praxis-ai-assistant-shell__assistant-resource-meta,.praxis-ai-assistant-shell__assistant-field-list,.praxis-ai-assistant-shell__assistant-evidence{display:flex;flex-wrap:wrap;gap:5px}.praxis-ai-assistant-shell__assistant-resource-meta span,.praxis-ai-assistant-shell__assistant-field,.praxis-ai-assistant-shell__assistant-evidence span{display:inline-flex;align-items:center;gap:4px;min-width:0;max-width:100%;padding:3px 6px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 62%,transparent);border-radius:999px;color:var(--md-sys-color-on-surface-variant);background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 82%,transparent);font-size:11px;line-height:1.25}.praxis-ai-assistant-shell__assistant-field{color:color-mix(in srgb,var(--md-sys-color-primary) 88%,var(--md-sys-color-on-surface));background:color-mix(in srgb,var(--md-sys-color-primary) 9%,transparent);border-color:color-mix(in srgb,var(--md-sys-color-primary) 22%,transparent)}.praxis-ai-assistant-shell__assistant-evidence span{color:color-mix(in srgb,var(--praxis-ai-assistant-shell-tone-success) 85%,var(--md-sys-color-on-surface));background:color-mix(in srgb,var(--praxis-ai-assistant-shell-tone-success) 9%,transparent);border-color:color-mix(in srgb,var(--praxis-ai-assistant-shell-tone-success) 22%,transparent)}.praxis-ai-assistant-shell__assistant-evidence mat-icon{width:13px;height:13px;font-size:13px}.praxis-ai-assistant-shell__assistant-resource p{margin:0;color:var(--md-sys-color-on-surface-variant)}.praxis-ai-assistant-shell__message-actions{display:flex;align-items:center;gap:4px;flex-wrap:wrap;margin-top:8px}.praxis-ai-assistant-shell__message-action{min-height:28px;padding:0 8px;border-radius:8px;font-size:12px}.praxis-ai-assistant-shell__message-action--icon{width:30px;min-width:30px;height:30px;padding:0;color:var(--md-sys-color-on-surface-variant)}.praxis-ai-assistant-shell__message-action--icon mat-icon{width:17px;height:17px;font-size:17px}.praxis-ai-assistant-shell__message-feedback,.praxis-ai-assistant-shell__message-feedback-submitted{display:flex;align-items:center;gap:4px;margin-top:8px}.praxis-ai-assistant-shell__message-feedback-action{--mdc-icon-button-state-layer-size: 30px;--mat-icon-button-state-layer-size: 30px;display:inline-grid;place-items:center;width:30px;min-width:30px;height:30px;padding:0;color:var(--md-sys-color-on-surface-variant);line-height:1}.praxis-ai-assistant-shell__message-feedback-action mat-icon,.praxis-ai-assistant-shell__message-feedback-submitted mat-icon{display:block;width:17px;height:17px;font-size:17px;line-height:17px}.praxis-ai-assistant-shell__message-feedback-submitted{color:var(--md-sys-color-on-surface-variant);font-size:12px}.praxis-ai-assistant-shell__message--assistant{border-bottom-left-radius:2px}.praxis-ai-assistant-shell__message--user{align-self:flex-end;border-bottom-right-radius:2px;background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}.praxis-ai-assistant-shell__message--status{color:var(--md-sys-color-on-surface-variant)}.praxis-ai-assistant-shell__message--error,.praxis-ai-assistant-shell__error{color:var(--md-sys-color-error)}.praxis-ai-assistant-shell__quick-replies{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,520px),1fr));gap:8px;align-items:stretch;padding-bottom:4px}.praxis-ai-assistant-shell__quick-replies--inline{display:flex;flex-wrap:wrap;align-items:center;gap:6px}.praxis-ai-assistant-shell__attachment{flex:0 0 auto;display:inline-flex;align-items:center;gap:7px;max-width:260px;min-height:34px;padding:4px 4px 4px 8px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 70%,transparent);border-radius:8px;background:var(--md-sys-color-surface-container-high)}.praxis-ai-assistant-shell__attachment--error{border-color:color-mix(in srgb,var(--md-sys-color-error) 60%,transparent)}.praxis-ai-assistant-shell__attachment-preview{flex:0 0 auto;width:28px;height:28px;border-radius:6px;object-fit:cover}.praxis-ai-assistant-shell__attachment-name,.praxis-ai-assistant-shell__attachment-kind{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:12px}.praxis-ai-assistant-shell__attachment-name{color:var(--md-sys-color-on-surface)}.praxis-ai-assistant-shell__attachment-kind{color:var(--md-sys-color-on-surface-variant)}.praxis-ai-assistant-shell__quick-reply{--praxis-ai-assistant-shell-quick-reply-accent: var(--md-sys-color-primary);--praxis-ai-assistant-shell-quick-reply-background: color-mix( in srgb, var(--praxis-ai-assistant-shell-quick-reply-accent) 7%, var(--md-sys-color-surface-container-high) );--praxis-ai-assistant-shell-quick-reply-foreground: var(--md-sys-color-on-surface);width:100%;max-width:100%;height:auto;min-height:0;position:relative;overflow:hidden;padding:15px 16px;align-items:stretch;border-color:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 36%,transparent);border-radius:22px;color:var(--praxis-ai-assistant-shell-quick-reply-foreground);background:linear-gradient(135deg,color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 16%,transparent),transparent 46%),radial-gradient(circle at 92% 10%,color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 22%,transparent),transparent 32%),var(--praxis-ai-assistant-shell-quick-reply-background);box-shadow:0 18px 42px color-mix(in srgb,var(--praxis-ai-assistant-shell-shadow-color) 22%,transparent),inset 0 1px color-mix(in srgb,var(--praxis-ai-assistant-shell-highlight-color) 16%,transparent);letter-spacing:normal;white-space:normal;text-align:left;text-transform:none;-webkit-user-select:none;user-select:none;transition:border-color .16s ease,box-shadow .16s ease,transform .16s ease,background .16s ease;--mdc-outlined-button-container-height: auto;--mat-outlined-button-horizontal-padding: 0}.praxis-ai-assistant-shell__quick-reply:hover:not(:disabled),.praxis-ai-assistant-shell__quick-reply:focus-visible{border-color:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 74%,transparent);box-shadow:0 18px 42px color-mix(in srgb,var(--praxis-ai-assistant-shell-shadow-color) 24%,transparent),0 0 0 3px color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 18%,transparent),inset 0 1px color-mix(in srgb,var(--praxis-ai-assistant-shell-highlight-color) 18%,transparent);transform:translateY(-1px)}.praxis-ai-assistant-shell__quick-reply--contextual-action{padding:10px 12px;border-color:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 34%,transparent);border-radius:8px;background:linear-gradient(90deg,color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 15%,transparent),color-mix(in srgb,var(--md-sys-color-surface-container-high) 92%,transparent)),var(--md-sys-color-surface-container-high);box-shadow:none}.praxis-ai-assistant-shell__quick-reply--guided-action{padding:10px 12px;border-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 82%,transparent);border-radius:8px;background:var(--md-sys-color-surface-container-high);box-shadow:none}.praxis-ai-assistant-shell__quick-reply--source-review{padding:11px 12px;border-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 88%,transparent);border-radius:8px;background:linear-gradient(90deg,color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 7%,transparent),transparent 58%),var(--md-sys-color-surface-container-high);box-shadow:none}.praxis-ai-assistant-shell__quick-reply--contextual-action:hover:not(:disabled),.praxis-ai-assistant-shell__quick-reply--contextual-action:focus-visible{border-color:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 62%,transparent);box-shadow:0 0 0 2px color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 15%,transparent);transform:none}.praxis-ai-assistant-shell__quick-reply--guided-action:hover:not(:disabled),.praxis-ai-assistant-shell__quick-reply--guided-action:focus-visible,.praxis-ai-assistant-shell__quick-reply--source-review:hover:not(:disabled),.praxis-ai-assistant-shell__quick-reply--source-review:focus-visible{border-color:color-mix(in srgb,var(--md-sys-color-primary) 64%,var(--md-sys-color-outline-variant));background:color-mix(in srgb,var(--md-sys-color-primary-container) 18%,var(--md-sys-color-surface-container-high));box-shadow:0 0 0 2px color-mix(in srgb,var(--md-sys-color-primary) 14%,transparent);transform:none}.praxis-ai-assistant-shell__quick-reply--contextual-action .praxis-ai-assistant-shell__quick-reply-ambient,.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-ambient,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-ambient{display:none}.praxis-ai-assistant-shell__quick-reply--contextual-action ::ng-deep .mdc-button__label,.praxis-ai-assistant-shell__quick-reply--guided-action ::ng-deep .mdc-button__label,.praxis-ai-assistant-shell__quick-reply--source-review ::ng-deep .mdc-button__label{gap:10px;align-items:flex-start}.praxis-ai-assistant-shell__quick-reply--contextual-action .praxis-ai-assistant-shell__quick-reply-icon-frame,.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-icon-frame,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-icon-frame{width:34px;height:34px;border-radius:8px;box-shadow:none}.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-icon-frame,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-icon-frame{border-color:color-mix(in srgb,var(--md-sys-color-primary) 24%,var(--md-sys-color-outline-variant));color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary-container) 34%,var(--md-sys-color-surface-container-high))}.praxis-ai-assistant-shell__quick-reply--contextual-action .praxis-ai-assistant-shell__quick-reply-icon,.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-icon,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-icon{width:19px;height:19px;font-size:19px}.praxis-ai-assistant-shell__quick-reply--contextual-action .praxis-ai-assistant-shell__quick-reply-copy,.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-copy,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-copy{gap:6px}.praxis-ai-assistant-shell__quick-reply--contextual-action .praxis-ai-assistant-shell__quick-reply-label,.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-label,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-label{font-size:13.5px;font-weight:760;letter-spacing:0}.praxis-ai-assistant-shell__quick-reply--contextual-action .praxis-ai-assistant-shell__quick-reply-description,.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-description,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-description{display:-webkit-box;overflow:hidden;font-size:12px;line-height:1.34;-webkit-box-orient:vertical;-webkit-line-clamp:2}.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-description{color:var(--md-sys-color-on-surface-variant)}.praxis-ai-assistant-shell__quick-reply--contextual-action .praxis-ai-assistant-shell__quick-reply-badge,.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-badge,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-badge{border-radius:8px;font-size:10px;letter-spacing:0}.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-badge,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-badge{border-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 76%,transparent);color:var(--md-sys-color-on-surface-variant);background:color-mix(in srgb,var(--md-sys-color-surface-container-lowest) 62%,transparent)}.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-cta,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-cta{color:var(--md-sys-color-primary)}.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-context{gap:5px}.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-context-chip{border-radius:8px;padding:4px 7px;background:color-mix(in srgb,var(--md-sys-color-surface-container-lowest) 66%,transparent);font-size:10.5px;font-weight:650}.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-actions{max-width:40%}.praxis-ai-assistant-shell__quick-reply--contextual-action .praxis-ai-assistant-shell__quick-reply-context-chip{border-radius:8px;padding:4px 7px;font-size:10.5px;font-weight:650}.praxis-ai-assistant-shell__quick-reply--contextual-action .praxis-ai-assistant-shell__quick-reply-cta,.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-cta,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-cta{font-size:11.5px}.praxis-ai-assistant-shell__quick-reply--compact{justify-self:start;width:fit-content;min-width:min(100%,210px);max-width:min(100%,320px);padding:9px 11px;border-radius:16px;background:linear-gradient(135deg,color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 10%,transparent),transparent 55%),var(--md-sys-color-surface-container-high);box-shadow:0 8px 18px color-mix(in srgb,var(--praxis-ai-assistant-shell-shadow-color) 16%,transparent),inset 0 1px color-mix(in srgb,var(--praxis-ai-assistant-shell-highlight-color) 10%,transparent)}.praxis-ai-assistant-shell__quick-reply.praxis-ai-assistant-shell__quick-reply--compact ::ng-deep .mdc-button__label{align-items:center;gap:10px}.praxis-ai-assistant-shell__quick-reply--compact .praxis-ai-assistant-shell__quick-reply-icon-frame{width:34px;height:34px;border-radius:12px}.praxis-ai-assistant-shell__quick-reply--compact .praxis-ai-assistant-shell__quick-reply-icon{width:19px;height:19px;font-size:19px}.praxis-ai-assistant-shell__quick-reply--compact .praxis-ai-assistant-shell__quick-reply-copy{gap:4px}.praxis-ai-assistant-shell__quick-reply--compact .praxis-ai-assistant-shell__quick-reply-header{align-items:center}.praxis-ai-assistant-shell__quick-reply--compact .praxis-ai-assistant-shell__quick-reply-label{font-size:13px;line-height:1.2}.praxis-ai-assistant-shell__quick-reply--compact .praxis-ai-assistant-shell__quick-reply-badge,.praxis-ai-assistant-shell__quick-reply--compact .praxis-ai-assistant-shell__quick-reply-cta{display:none}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply{width:auto;min-width:0;max-width:100%;padding:6px 10px;border-radius:999px;box-shadow:none}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply--guided-action{border-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 76%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container-high) 96%,transparent)}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply--guided-action:hover:not(:disabled),.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply--guided-action:focus-visible{border-color:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 52%,transparent);background:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 9%,var(--md-sys-color-surface-container-high));box-shadow:0 0 0 2px color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 12%,transparent)}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply ::ng-deep .mdc-button__label{display:inline-flex;grid-template-columns:none;align-items:center;gap:6px;width:auto}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply ::ng-deep .mat-mdc-button-touch-target{min-height:34px}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-icon-frame{width:18px;height:18px;border:0;border-radius:0;background:transparent;box-shadow:none}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-icon{width:16px;height:16px;color:var(--praxis-ai-assistant-shell-quick-reply-accent);font-size:16px}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-copy,.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-heading,.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-header{display:inline-flex;align-items:center;gap:0}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-label{color:var(--md-sys-color-on-surface);font-size:12.5px;font-weight:650;line-height:1.2;white-space:nowrap}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-description,.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-actions,.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-badge,.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-cta{display:none}.praxis-ai-assistant-shell__quick-reply ::ng-deep .mdc-button__label{position:relative;z-index:1;min-width:0;display:grid;grid-template-columns:auto minmax(0,1fr);align-items:flex-start;gap:14px;width:100%;height:auto;line-height:normal}.praxis-ai-assistant-shell__quick-reply-ambient{position:absolute;inset:0;pointer-events:none}.praxis-ai-assistant-shell__quick-reply-ambient:before{content:\"\";position:absolute;inset:0 18px auto;height:1px;border-radius:999px;background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 90%,var(--praxis-ai-assistant-shell-highlight-color)),transparent);opacity:.58}.praxis-ai-assistant-shell__quick-reply-ambient:after{content:\"\";position:absolute;top:-34px;right:-44px;width:150px;height:150px;border-radius:999px;background:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 13%,transparent);filter:blur(18px)}.praxis-ai-assistant-shell__quick-reply ::ng-deep .mat-mdc-button-touch-target{height:100%;min-height:48px}.praxis-ai-assistant-shell__quick-reply-icon-frame{flex:0 0 auto;width:46px;height:46px;display:inline-grid;place-items:center;border:1px solid color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 34%,transparent);border-radius:17px;color:var(--praxis-ai-assistant-shell-quick-reply-accent);background:linear-gradient(145deg,color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 24%,transparent),color-mix(in srgb,var(--praxis-ai-assistant-shell-highlight-color) 6%,transparent));box-shadow:inset 0 1px color-mix(in srgb,var(--praxis-ai-assistant-shell-highlight-color) 18%,transparent),0 10px 24px color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 12%,transparent)}.praxis-ai-assistant-shell__quick-reply-icon{width:24px;height:24px;font-size:24px}.praxis-ai-assistant-shell__quick-reply-details{flex:0 0 auto;width:24px;height:24px;display:inline-grid;place-items:center;border:1px solid color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 14%,transparent);border-radius:50%;color:var(--md-sys-color-on-surface-variant);background:color-mix(in srgb,var(--md-sys-color-outline) 14%,transparent);font-size:17px;opacity:.9}.praxis-ai-assistant-shell__quick-reply-copy{min-width:0;display:grid;gap:10px;flex:1 1 auto}.praxis-ai-assistant-shell__quick-reply-header{min-width:0;display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.praxis-ai-assistant-shell__quick-reply-heading{min-width:0;display:grid;gap:5px}.praxis-ai-assistant-shell__quick-reply-actions{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:flex-end;gap:7px;max-width:46%}.praxis-ai-assistant-shell__quick-reply-label,.praxis-ai-assistant-shell__quick-reply-description{min-width:0;overflow-wrap:anywhere}.praxis-ai-assistant-shell__quick-reply-label{color:var(--md-sys-color-on-surface);font-size:17px;font-weight:760;letter-spacing:.005em;line-height:1.18;text-transform:none}.praxis-ai-assistant-shell__quick-reply-badge{flex:0 0 auto;max-width:100%;padding:4px 8px;border:1px solid color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 28%,transparent);border-radius:999px;color:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 86%,var(--praxis-ai-assistant-shell-highlight-color));background:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 11%,transparent);font-size:10.5px;font-weight:700;letter-spacing:.02em;line-height:1.1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.praxis-ai-assistant-shell__quick-reply-description{color:color-mix(in srgb,var(--md-sys-color-on-surface) 80%,transparent);font-size:13px;line-height:1.46}.praxis-ai-assistant-shell__quick-reply-context{display:flex;flex-wrap:wrap;gap:7px;align-items:center}.praxis-ai-assistant-shell__quick-reply-context-chip{min-width:0;display:inline-flex;align-items:center;gap:4px;max-width:100%;padding:5px 8px;border:1px solid color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 22%,transparent);border-radius:999px;color:color-mix(in srgb,var(--md-sys-color-on-surface) 82%,transparent);background:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 9%,transparent);font-size:11px;font-weight:650;line-height:1.15}.praxis-ai-assistant-shell__quick-reply-context-chip mat-icon{width:14px;height:14px;color:var(--praxis-ai-assistant-shell-quick-reply-accent);font-size:14px}.praxis-ai-assistant-shell__quick-reply-context-chip span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.praxis-ai-assistant-shell__quick-reply-insights{display:grid;grid-template-columns:repeat(auto-fit,minmax(145px,1fr));gap:8px;padding:8px;border:1px solid color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 16%,transparent);border-radius:16px;background:linear-gradient(180deg,color-mix(in srgb,var(--praxis-ai-assistant-shell-highlight-color) 5%,transparent),color-mix(in srgb,var(--md-sys-color-surface-container-lowest) 26%,transparent))}.praxis-ai-assistant-shell__quick-reply-insight{min-width:0;display:grid;grid-template-columns:20px minmax(0,1fr);gap:8px;align-items:start;padding:8px;border:1px solid color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 10%,transparent);border-radius:13px;color:color-mix(in srgb,var(--md-sys-color-on-surface) 86%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container-high) 44%,transparent);font-size:12px;line-height:1.35}.praxis-ai-assistant-shell__quick-reply-insight mat-icon{width:17px;height:17px;color:var(--praxis-ai-assistant-shell-quick-reply-accent);font-size:17px;opacity:.9}.praxis-ai-assistant-shell__quick-reply-insight-copy{min-width:0;display:grid;gap:1px}.praxis-ai-assistant-shell__quick-reply-insight-label{color:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 82%,var(--praxis-ai-assistant-shell-highlight-color));font-size:10.5px;font-weight:760;letter-spacing:.045em;line-height:1.2;text-transform:uppercase}.praxis-ai-assistant-shell__quick-reply-insight-value{min-width:0;overflow-wrap:anywhere}.praxis-ai-assistant-shell__quick-reply-cta{display:inline-flex;align-items:center;justify-self:start;gap:5px;padding:3px 0;color:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 84%,var(--praxis-ai-assistant-shell-highlight-color));font-size:12px;font-weight:760;letter-spacing:.01em;line-height:1.2}.praxis-ai-assistant-shell__quick-reply-cta mat-icon{width:15px;height:15px;font-size:15px;transition:transform .16s ease}.praxis-ai-assistant-shell__quick-reply:hover:not(:disabled) .praxis-ai-assistant-shell__quick-reply-cta mat-icon,.praxis-ai-assistant-shell__quick-reply:focus-visible .praxis-ai-assistant-shell__quick-reply-cta mat-icon{transform:translate(2px)}.praxis-ai-assistant-shell__quick-reply--tone-analytics{--praxis-ai-assistant-shell-quick-reply-accent: var(--praxis-ai-assistant-shell-tone-analytics)}.praxis-ai-assistant-shell__quick-reply--tone-resource{--praxis-ai-assistant-shell-quick-reply-accent: var(--praxis-ai-assistant-shell-tone-resource)}.praxis-ai-assistant-shell__quick-reply--tone-warning{--praxis-ai-assistant-shell-quick-reply-accent: var(--praxis-ai-assistant-shell-tone-warning)}.praxis-ai-assistant-shell__quick-reply--tone-success{--praxis-ai-assistant-shell-quick-reply-accent: var(--praxis-ai-assistant-shell-tone-success)}.praxis-ai-assistant-shell__quick-reply--tone-danger{--praxis-ai-assistant-shell-quick-reply-accent: var(--praxis-ai-assistant-shell-tone-danger)}.praxis-ai-assistant-shell__quick-reply--tone-neutral{--praxis-ai-assistant-shell-quick-reply-accent: var(--praxis-ai-assistant-shell-tone-neutral)}@media(max-width:640px){.praxis-ai-assistant-shell__context{flex-wrap:wrap;overflow-x:visible}.praxis-ai-assistant-shell__context-item{max-width:min(100%,240px)}.praxis-ai-assistant-shell__quick-reply{padding:13px;border-radius:19px}.praxis-ai-assistant-shell__quick-reply ::ng-deep .mdc-button__label{grid-template-columns:minmax(0,1fr);gap:10px}.praxis-ai-assistant-shell__quick-reply-icon-frame{width:38px;height:38px;border-radius:14px}.praxis-ai-assistant-shell__quick-reply-header{display:grid}.praxis-ai-assistant-shell__quick-reply-actions{justify-content:flex-start;max-width:100%}.praxis-ai-assistant-shell__quick-reply-insights{grid-template-columns:minmax(0,1fr)}}@container (max-width: 400px){.praxis-ai-assistant-shell__header{display:grid;grid-template-columns:auto minmax(0,1fr) auto}.praxis-ai-assistant-shell__title-row{display:grid;gap:5px}.praxis-ai-assistant-shell__badges{justify-content:flex-start}.praxis-ai-assistant-shell__badge{max-width:100%}.praxis-ai-assistant-shell__context{flex-wrap:wrap;overflow-x:visible}.praxis-ai-assistant-shell__context-item{flex:1 1 150px;max-width:100%}.praxis-ai-assistant-shell__context-label,.praxis-ai-assistant-shell__context-value{overflow:visible;text-overflow:clip;white-space:normal;overflow-wrap:anywhere}.praxis-ai-assistant-shell__recommended-title-row,.praxis-ai-assistant-shell__assistant-resource-head{display:grid;justify-content:stretch}.praxis-ai-assistant-shell__recommended-group{max-width:100%;width:fit-content}.praxis-ai-assistant-shell__assistant-resource-head strong{overflow:visible;text-overflow:clip;white-space:normal;overflow-wrap:anywhere}}.praxis-ai-assistant-shell__status,.praxis-ai-assistant-shell__error{margin:0;font-size:13px;line-height:1.35;overflow-wrap:anywhere}.praxis-ai-assistant-shell__footer{flex:0 0 auto;padding:8px 10px 10px;border-top:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 72%,transparent);background:var(--md-sys-color-surface-container-low)}.praxis-ai-assistant-shell__composer{display:grid;gap:8px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container-lowest);box-shadow:inset 0 1px color-mix(in srgb,var(--praxis-ai-assistant-shell-highlight-color) 4%,transparent)}.praxis-ai-assistant-shell__composer:focus-within{border-color:var(--md-sys-color-primary);box-shadow:0 0 0 2px color-mix(in srgb,var(--md-sys-color-primary) 16%,transparent)}.praxis-ai-assistant-shell__composer-actions{display:flex;align-items:center;justify-content:flex-end;gap:8px;padding:0 8px 7px;flex-wrap:wrap}.praxis-ai-assistant-shell__voice-action{color:var(--md-sys-color-on-surface-variant)}.praxis-ai-assistant-shell__voice-action--active{color:var(--md-sys-color-error);background:color-mix(in srgb,var(--md-sys-color-error) 10%,transparent)}.praxis-ai-assistant-shell__voice-action--error{color:var(--praxis-ai-assistant-shell-tone-warning)}.praxis-ai-assistant-shell__voice-status{margin:-2px 10px 8px;color:var(--md-sys-color-on-surface-variant);font-size:12px;line-height:1.3}.praxis-ai-assistant-shell__action{min-height:36px;border-radius:10px;font-weight:650}.praxis-ai-assistant-shell__action mat-icon{width:18px;height:18px;margin-right:6px;font-size:18px}.praxis-ai-assistant-shell__action--icon-only{width:40px;min-width:40px;height:40px;padding-inline:0;border-radius:50%}.praxis-ai-assistant-shell__action--icon-only mat-icon{margin-right:0}.praxis-ai-assistant-shell__action--secondary{color:var(--md-sys-color-on-surface-variant)}.praxis-ai-assistant-shell__action--tone-governance{color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 10%,transparent)}.praxis-ai-assistant-shell__action--tone-success{color:var(--praxis-ai-assistant-shell-tone-success);background:color-mix(in srgb,var(--praxis-ai-assistant-shell-tone-success) 10%,transparent)}.praxis-ai-assistant-shell__action--tone-warning{color:var(--praxis-ai-assistant-shell-tone-warning);background:color-mix(in srgb,var(--praxis-ai-assistant-shell-tone-warning) 10%,transparent)}.praxis-ai-assistant-shell__action--tone-danger{color:var(--md-sys-color-error);background:color-mix(in srgb,var(--md-sys-color-error) 10%,transparent)}.praxis-ai-assistant-shell__resize-handle{position:absolute;z-index:2;border:0;background:transparent;touch-action:none}.praxis-ai-assistant-shell__resize-handle--n,.praxis-ai-assistant-shell__resize-handle--s{left:16px;right:16px;height:10px;cursor:ns-resize}.praxis-ai-assistant-shell__resize-handle--n{top:-5px}.praxis-ai-assistant-shell__resize-handle--s{bottom:-5px}.praxis-ai-assistant-shell__resize-handle--e,.praxis-ai-assistant-shell__resize-handle--w{top:16px;bottom:16px;width:10px;cursor:ew-resize}.praxis-ai-assistant-shell__resize-handle--e{right:-5px}.praxis-ai-assistant-shell__resize-handle--w{left:-5px}.praxis-ai-assistant-shell__resize-handle--ne,.praxis-ai-assistant-shell__resize-handle--nw,.praxis-ai-assistant-shell__resize-handle--se,.praxis-ai-assistant-shell__resize-handle--sw{width:22px;height:22px}.praxis-ai-assistant-shell__resize-handle--ne{top:-5px;right:-5px;cursor:nesw-resize}.praxis-ai-assistant-shell__resize-handle--nw{top:-5px;left:-5px;cursor:nwse-resize}.praxis-ai-assistant-shell__resize-handle--se{right:-5px;bottom:-5px;cursor:nwse-resize}.praxis-ai-assistant-shell__resize-handle--sw{bottom:-5px;left:-5px;cursor:nesw-resize}.praxis-ai-assistant-shell__resize-handle--se:after{content:\"\";position:absolute;right:8px;bottom:8px;width:10px;height:10px;border-right:2px solid var(--md-sys-color-outline);border-bottom:2px solid var(--md-sys-color-outline)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.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: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i7.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i8.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
9819
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PraxisAiAssistantShellComponent, isStandalone: true, selector: "praxis-ai-assistant-shell", inputs: { labels: "labels", mode: "mode", state: "state", contextItems: "contextItems", attachments: "attachments", messages: "messages", quickReplies: "quickReplies", recommendedIntents: "recommendedIntents", prompt: "prompt", statusText: "statusText", errorText: "errorText", testIdPrefix: "testIdPrefix", panelTestId: "panelTestId", submitTestId: "submitTestId", applyTestId: "applyTestId", primaryAction: "primaryAction", secondaryActions: "secondaryActions", governanceActions: "governanceActions", busy: "busy", canSubmit: "canSubmit", canApply: "canApply", submitOnEnter: "submitOnEnter", showAttachAction: "showAttachAction", enablePastedAttachments: "enablePastedAttachments", enableFileAttachments: "enableFileAttachments", attachmentAccept: "attachmentAccept", attachmentMultiple: "attachmentMultiple", voiceInputMode: "voiceInputMode", voiceLanguage: "voiceLanguage", draggable: "draggable", resizable: "resizable", minWidth: "minWidth", minHeight: "minHeight", margin: "margin", layout: "layout" }, outputs: { promptChange: "promptChange", submitPrompt: "submitPrompt", apply: "apply", retryTurn: "retryTurn", cancelTurn: "cancelTurn", shellAction: "shellAction", close: "close", attach: "attach", attachmentsPasted: "attachmentsPasted", attachmentsSelected: "attachmentsSelected", removeAttachment: "removeAttachment", messageAction: "messageAction", editMessage: "editMessage", resendMessage: "resendMessage", quickReply: "quickReply", recommendedIntent: "recommendedIntent", layoutChange: "layoutChange" }, host: { listeners: { "window:resize": "onViewportResize()" } }, providers: [PraxisBrowserSpeechTranscriptionService], viewQueries: [{ propertyName: "panel", first: true, predicate: ["panel"], descendants: true, static: true }, { propertyName: "conversation", first: true, predicate: ["conversation"], descendants: true }, { propertyName: "promptInput", first: true, predicate: ["promptInput"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<section\n #panel\n class=\"praxis-ai-assistant-shell\"\n role=\"dialog\"\n [attr.aria-label]=\"resolvedLabels.title\"\n [attr.aria-busy]=\"busy ? 'true' : null\"\n [style.left.px]=\"currentLayout.left\"\n [style.top.px]=\"currentLayout.top\"\n [style.width.px]=\"currentLayout.width\"\n [style.height.px]=\"currentLayout.height\"\n [attr.data-testid]=\"panelTestId || testIdPrefix\"\n [attr.data-mode]=\"mode\"\n [attr.data-state]=\"state\"\n >\n <header\n class=\"praxis-ai-assistant-shell__header\"\n [attr.data-testid]=\"testIdPrefix + '-drag-handle'\"\n [attr.aria-label]=\"resolvedLabels.dragHandleAria\"\n (pointerdown)=\"startDrag($event)\"\n >\n <div class=\"praxis-ai-assistant-shell__identity\" aria-hidden=\"true\">\n <mat-icon>auto_awesome</mat-icon>\n </div>\n <div class=\"praxis-ai-assistant-shell__title-group\">\n <div class=\"praxis-ai-assistant-shell__title-row\">\n <strong>{{ resolvedLabels.title }}</strong>\n <div class=\"praxis-ai-assistant-shell__badges\" aria-hidden=\"true\">\n <span class=\"praxis-ai-assistant-shell__badge praxis-ai-assistant-shell__badge--context\">\n {{ getModeLabel() }}\n </span>\n <span\n class=\"praxis-ai-assistant-shell__badge praxis-ai-assistant-shell__badge--state\"\n [class.praxis-ai-assistant-shell__badge--error]=\"state === 'error'\"\n >\n <span class=\"praxis-ai-assistant-shell__state-dot\" aria-hidden=\"true\"></span>\n {{ getStateLabel() }}\n </span>\n </div>\n </div>\n @if (resolvedLabels.subtitle) {\n <p>{{ resolvedLabels.subtitle }}</p>\n }\n </div>\n <div class=\"praxis-ai-assistant-shell__header-actions\">\n <button\n [praxisIconButton]=\"getCloseIcon()\"\n size=\"compact\"\n type=\"button\"\n [matTooltip]=\"resolvedLabels.close\"\n [attr.aria-label]=\"resolvedLabels.close\"\n (pointerdown)=\"$event.stopPropagation()\"\n (click)=\"close.emit()\"\n [attr.data-testid]=\"testIdPrefix + '-close'\"\n ></button>\n </div>\n </header>\n\n <div class=\"praxis-ai-assistant-shell__body\">\n @if (contextItems.length) {\n <div\n class=\"praxis-ai-assistant-shell__context\"\n [attr.aria-label]=\"resolvedLabels.contextAria\"\n [attr.data-testid]=\"testIdPrefix + '-context'\"\n >\n @for (item of contextItems; track trackContextItem($index, item)) {\n <span\n class=\"praxis-ai-assistant-shell__context-item\"\n [attr.data-testid]=\"testIdPrefix + '-context-' + item.id\"\n >\n @if (item.icon) {\n <mat-icon aria-hidden=\"true\">{{ item.icon }}</mat-icon>\n }\n <span class=\"praxis-ai-assistant-shell__context-label\">{{ item.label }}</span>\n @if (item.value) {\n <span class=\"praxis-ai-assistant-shell__context-value\">{{ getContextItemValue(item) }}</span>\n }\n </span>\n }\n </div>\n }\n\n @if (shouldShowRecommendedIntents()) {\n <section\n class=\"praxis-ai-assistant-shell__recommended\"\n [attr.aria-label]=\"resolvedLabels.recommendedIntentsAria\"\n [attr.data-testid]=\"testIdPrefix + '-recommended-intents'\"\n >\n <div class=\"praxis-ai-assistant-shell__recommended-header\">\n <mat-icon aria-hidden=\"true\">auto_awesome</mat-icon>\n <span>{{ resolvedLabels.recommendedIntentsTitle }}</span>\n </div>\n <div class=\"praxis-ai-assistant-shell__recommended-list\">\n @for (intent of recommendedIntents; track trackRecommendedIntent($index, intent)) {\n <button\n type=\"button\"\n class=\"praxis-ai-assistant-shell__recommended-intent\"\n [ngClass]=\"'praxis-ai-assistant-shell__recommended-intent--tone-' + getRecommendedIntentTone(intent)\"\n [attr.data-testid]=\"testIdPrefix + '-recommended-intent-' + intent.id\"\n [attr.aria-label]=\"getRecommendedIntentAriaLabel(intent)\"\n [disabled]=\"isRecommendedIntentDisabled(intent)\"\n (click)=\"onRecommendedIntent(intent)\"\n >\n <span class=\"praxis-ai-assistant-shell__recommended-icon\" aria-hidden=\"true\">\n <mat-icon>{{ getRecommendedIntentIcon(intent) }}</mat-icon>\n </span>\n <span class=\"praxis-ai-assistant-shell__recommended-copy\">\n <span class=\"praxis-ai-assistant-shell__recommended-title-row\">\n <span class=\"praxis-ai-assistant-shell__recommended-title\">{{ intent.label }}</span>\n @if (getRecommendedIntentGroupLabel(intent)) {\n <span class=\"praxis-ai-assistant-shell__recommended-group\">\n {{ getRecommendedIntentGroupLabel(intent) }}\n </span>\n }\n </span>\n @if (getRecommendedIntentDescription(intent)) {\n <span class=\"praxis-ai-assistant-shell__recommended-description\">\n {{ getRecommendedIntentDescription(intent) }}\n </span>\n }\n <span class=\"praxis-ai-assistant-shell__recommended-cta\">\n @if (intent.requiresConfirmation && !intent.disabledReason) {\n <span>{{ resolvedLabels.recommendedIntentRequiresConfirmation }}</span>\n }\n <span>{{ getRecommendedIntentCtaLabel(intent) }}</span>\n <mat-icon aria-hidden=\"true\">arrow_forward</mat-icon>\n </span>\n </span>\n </button>\n }\n </div>\n </section>\n }\n\n <div\n #conversation\n class=\"praxis-ai-assistant-shell__conversation\"\n [attr.data-testid]=\"testIdPrefix + '-conversation'\"\n [attr.aria-label]=\"resolvedLabels.conversationAria\"\n >\n @if (!messages.length) {\n <article\n class=\"praxis-ai-assistant-shell__message praxis-ai-assistant-shell__message--assistant\"\n [attr.data-testid]=\"testIdPrefix + '-message-assistant-empty'\"\n >\n {{ resolvedLabels.emptyConversation }}\n </article>\n }\n @for (message of messages; track trackMessage($index, message)) {\n <article\n class=\"praxis-ai-assistant-shell__message\"\n [class.praxis-ai-assistant-shell__message--user]=\"message.role === 'user'\"\n [class.praxis-ai-assistant-shell__message--assistant]=\"message.role === 'assistant'\"\n [class.praxis-ai-assistant-shell__message--status]=\"message.role === 'status'\"\n [class.praxis-ai-assistant-shell__message--error]=\"message.role === 'error'\"\n [attr.data-testid]=\"testIdPrefix + '-message-' + message.role\"\n >\n <div\n class=\"praxis-ai-assistant-shell__message-content\"\n >\n @if (hasStructuredAssistantContent(message)) {\n <div class=\"praxis-ai-assistant-shell__assistant-content\">\n @for (block of getAssistantContentBlocks(message); track trackAssistantContentBlock($index, block)) {\n @switch (getAssistantContentBlockType(block)) {\n @case ('paragraph') {\n <section class=\"praxis-ai-assistant-shell__assistant-block praxis-ai-assistant-shell__assistant-block--summary\">\n <span class=\"praxis-ai-assistant-shell__assistant-block-icon\" aria-hidden=\"true\">\n <mat-icon>lightbulb</mat-icon>\n </span>\n <div\n class=\"praxis-ai-assistant-shell__assistant-block-copy\"\n [innerHTML]=\"renderMessageText(getAssistantContentBlockText(block))\"\n ></div>\n </section>\n }\n @case ('resource-list') {\n <section class=\"praxis-ai-assistant-shell__assistant-block\">\n <div class=\"praxis-ai-assistant-shell__assistant-block-heading\">\n <mat-icon aria-hidden=\"true\">database</mat-icon>\n <span>{{ getAssistantContentBlockTitle(block, 'Fontes confirmadas') }}</span>\n </div>\n <div class=\"praxis-ai-assistant-shell__assistant-resources\">\n @for (resource of getAssistantContentResources(block); track trackAssistantContentResource($index, resource)) {\n <article class=\"praxis-ai-assistant-shell__assistant-resource\">\n <div class=\"praxis-ai-assistant-shell__assistant-resource-head\">\n <strong>{{ resource.label }}</strong>\n @if (getAssistantContentResourceMeta(resource).length) {\n <span class=\"praxis-ai-assistant-shell__assistant-resource-meta\">\n @for (item of getAssistantContentResourceMeta(resource); track trackAssistantContentValue($index, item)) {\n <span>{{ item }}</span>\n }\n </span>\n }\n </div>\n @if (resource.description) {\n <p>{{ resource.description }}</p>\n }\n @if (resource.fields.length) {\n <div class=\"praxis-ai-assistant-shell__assistant-field-list\" aria-label=\"Campos dispon\u00EDveis\">\n @for (field of resource.fields; track trackAssistantContentField($index, field)) {\n <span\n class=\"praxis-ai-assistant-shell__assistant-field\"\n [matTooltip]=\"field.description || field.name\"\n >\n {{ field.label }}\n </span>\n }\n </div>\n }\n @if (resource.evidence.length) {\n <div class=\"praxis-ai-assistant-shell__assistant-evidence\" aria-label=\"Evid\u00EAncias\">\n @for (item of resource.evidence; track trackAssistantContentValue($index, item)) {\n <span>\n <mat-icon aria-hidden=\"true\">verified</mat-icon>\n {{ item }}\n </span>\n }\n </div>\n }\n </article>\n }\n </div>\n </section>\n }\n @case ('recommendation') {\n <section class=\"praxis-ai-assistant-shell__assistant-block praxis-ai-assistant-shell__assistant-block--recommendation\">\n <span class=\"praxis-ai-assistant-shell__assistant-block-icon\" aria-hidden=\"true\">\n <mat-icon>recommend</mat-icon>\n </span>\n <div class=\"praxis-ai-assistant-shell__assistant-block-copy\">\n <strong>{{ getAssistantContentBlockTitle(block, 'Recomenda\u00E7\u00E3o') }}</strong>\n <p>{{ getAssistantContentBlockText(block) }}</p>\n </div>\n </section>\n }\n }\n }\n </div>\n } @else {\n <div [innerHTML]=\"renderMessageText(message.text)\"></div>\n }\n </div>\n @if (message.actions?.length || message.editable || message.resendable) {\n <div\n class=\"praxis-ai-assistant-shell__message-actions\"\n >\n @if (message.editable) {\n <button\n praxisIconButton=\"edit\"\n size=\"dense\"\n type=\"button\"\n class=\"praxis-ai-assistant-shell__message-action praxis-ai-assistant-shell__message-action--icon\"\n [disabled]=\"busy\"\n [matTooltip]=\"resolvedLabels.editMessage\"\n [attr.aria-label]=\"resolvedLabels.editMessage\"\n [attr.data-testid]=\"testIdPrefix + '-message-edit-' + message.id\"\n (click)=\"onMessageAction(message, { id: 'edit', label: resolvedLabels.editMessage, kind: 'edit' })\"\n ></button>\n }\n @if (message.resendable) {\n <button\n praxisIconButton=\"replay\"\n size=\"dense\"\n type=\"button\"\n class=\"praxis-ai-assistant-shell__message-action praxis-ai-assistant-shell__message-action--icon\"\n [disabled]=\"busy\"\n [matTooltip]=\"resolvedLabels.resendMessage\"\n [attr.aria-label]=\"resolvedLabels.resendMessage\"\n [attr.data-testid]=\"testIdPrefix + '-message-resend-' + message.id\"\n (click)=\"onMessageAction(message, { id: 'resend', label: resolvedLabels.resendMessage, kind: 'resend' })\"\n ></button>\n }\n @for (action of message.actions || []; track trackMessageAction($index, action)) {\n @if (isMessageActionIconOnly(action)) {\n <button\n [praxisIconButton]=\"getMessageActionIcon(action)\"\n size=\"dense\"\n type=\"button\"\n class=\"praxis-ai-assistant-shell__message-action praxis-ai-assistant-shell__message-action--icon\"\n [disabled]=\"busy || action.disabled\"\n [matTooltip]=\"getMessageActionLabel(action)\"\n [attr.aria-label]=\"getMessageActionLabel(action)\"\n [attr.data-testid]=\"testIdPrefix + '-message-action-' + message.id + '-' + action.id\"\n (click)=\"onMessageAction(message, action)\"\n ></button>\n } @else {\n <button\n mat-button\n type=\"button\"\n class=\"praxis-ai-assistant-shell__message-action\"\n [disabled]=\"busy || action.disabled\"\n [attr.aria-label]=\"getMessageActionLabel(action)\"\n [attr.data-testid]=\"testIdPrefix + '-message-action-' + message.id + '-' + action.id\"\n (click)=\"onMessageAction(message, action)\"\n >\n {{ action.label }}\n </button>\n }\n }\n </div>\n }\n @if (canSendMessageFeedback(message)) {\n <div class=\"praxis-ai-assistant-shell__message-feedback\">\n <button\n praxisIconButton=\"thumb_up\"\n size=\"dense\"\n type=\"button\"\n class=\"praxis-ai-assistant-shell__message-feedback-action\"\n [disabled]=\"busy\"\n [matTooltip]=\"resolvedLabels.feedbackPositive\"\n [attr.aria-label]=\"resolvedLabels.feedbackPositive\"\n [attr.data-testid]=\"testIdPrefix + '-message-feedback-positive-' + message.id\"\n (click)=\"sendMessageFeedback(message, 'positive')\"\n ></button>\n <button\n praxisIconButton=\"thumb_down\"\n size=\"dense\"\n type=\"button\"\n class=\"praxis-ai-assistant-shell__message-feedback-action\"\n [disabled]=\"busy\"\n [matTooltip]=\"resolvedLabels.feedbackNegative\"\n [attr.aria-label]=\"resolvedLabels.feedbackNegative\"\n [attr.data-testid]=\"testIdPrefix + '-message-feedback-negative-' + message.id\"\n (click)=\"sendMessageFeedback(message, 'negative')\"\n ></button>\n </div>\n } @else if (isMessageFeedbackSubmitted(message)) {\n <div\n class=\"praxis-ai-assistant-shell__message-feedback-submitted\"\n [attr.data-testid]=\"testIdPrefix + '-message-feedback-submitted-' + message.id\"\n >\n <mat-icon aria-hidden=\"true\">check</mat-icon>\n <span>{{ resolvedLabels.feedbackSubmitted }}</span>\n </div>\n }\n </article>\n }\n </div>\n\n @if (attachments.length) {\n <div\n class=\"praxis-ai-assistant-shell__attachments\"\n [attr.aria-label]=\"resolvedLabels.attachmentsAria\"\n [attr.data-testid]=\"testIdPrefix + '-attachments'\"\n >\n @for (attachment of attachments; track trackAttachment($index, attachment)) {\n <div\n class=\"praxis-ai-assistant-shell__attachment\"\n [class.praxis-ai-assistant-shell__attachment--error]=\"attachment.status === 'error'\"\n [attr.data-testid]=\"testIdPrefix + '-attachment-' + attachment.id\"\n >\n @if (attachment.previewUrl && attachment.kind === 'image') {\n <img\n class=\"praxis-ai-assistant-shell__attachment-preview\"\n [src]=\"attachment.previewUrl\"\n [alt]=\"attachment.name\"\n >\n }\n <span class=\"praxis-ai-assistant-shell__attachment-name\">{{ attachment.name }}</span>\n <span class=\"praxis-ai-assistant-shell__attachment-kind\">{{ attachment.kind }}</span>\n <button\n praxisIconButton=\"close\"\n size=\"dense\"\n type=\"button\"\n [disabled]=\"busy\"\n [matTooltip]=\"resolvedLabels.removeAttachment\"\n [attr.aria-label]=\"resolvedLabels.removeAttachment + ': ' + attachment.name\"\n [attr.data-testid]=\"testIdPrefix + '-attachment-remove-' + attachment.id\"\n (click)=\"onRemoveAttachment(attachment)\"\n ></button>\n </div>\n }\n </div>\n }\n\n @if (quickReplies.length) {\n <div\n class=\"praxis-ai-assistant-shell__quick-replies\"\n [class.praxis-ai-assistant-shell__quick-replies--inline]=\"shouldUseInlineQuickReplies()\"\n [attr.data-testid]=\"testIdPrefix + '-quick-replies'\"\n [attr.aria-label]=\"resolvedLabels.quickRepliesAria\"\n >\n @for (reply of quickReplies; track trackQuickReply($index, reply)) {\n <button\n mat-stroked-button\n type=\"button\"\n class=\"praxis-ai-assistant-shell__quick-reply\"\n [class.praxis-ai-assistant-shell__quick-reply--compact]=\"!isRichQuickReply(reply)\"\n [class.praxis-ai-assistant-shell__quick-reply--guided-action]=\"isGuidedActionQuickReply(reply)\"\n [class.praxis-ai-assistant-shell__quick-reply--conversation-action]=\"isConversationQuickActionQuickReply(reply)\"\n [class.praxis-ai-assistant-shell__quick-reply--contextual-action]=\"isContextualPreviewActionQuickReply(reply)\"\n [class.praxis-ai-assistant-shell__quick-reply--source-review]=\"isSourceReviewQuickReply(reply)\"\n [ngClass]=\"'praxis-ai-assistant-shell__quick-reply--tone-' + getQuickReplyTone(reply)\"\n [attr.data-testid]=\"testIdPrefix + '-quick-reply-' + (reply.id || reply.kind)\"\n [attr.aria-label]=\"getQuickReplyAriaLabel(reply)\"\n [disabled]=\"busy\"\n (click)=\"onQuickReply(reply)\"\n >\n <span class=\"praxis-ai-assistant-shell__quick-reply-ambient\" aria-hidden=\"true\"></span>\n <span class=\"praxis-ai-assistant-shell__quick-reply-icon-frame\" aria-hidden=\"true\">\n <mat-icon\n class=\"praxis-ai-assistant-shell__quick-reply-icon\"\n >\n {{ getQuickReplyIcon(reply) }}\n </mat-icon>\n </span>\n <span class=\"praxis-ai-assistant-shell__quick-reply-copy\">\n <span class=\"praxis-ai-assistant-shell__quick-reply-header\">\n <span class=\"praxis-ai-assistant-shell__quick-reply-heading\">\n <span class=\"praxis-ai-assistant-shell__quick-reply-label\">{{ getQuickReplyLabel(reply) }}</span>\n @if (!isConversationQuickActionQuickReply(reply) && getQuickReplyDescription(reply)) {\n <span\n class=\"praxis-ai-assistant-shell__quick-reply-description\"\n >\n {{ getQuickReplyDescription(reply) }}\n </span>\n }\n </span>\n @if (!isConversationQuickActionQuickReply(reply)) {\n <span class=\"praxis-ai-assistant-shell__quick-reply-actions\">\n <span class=\"praxis-ai-assistant-shell__quick-reply-badge\">\n {{ getQuickReplyCategoryLabel(reply) }}\n </span>\n @if (getQuickReplyTechnicalDetails(reply)) {\n <mat-icon\n class=\"praxis-ai-assistant-shell__quick-reply-details\"\n [matTooltip]=\"getQuickReplyTechnicalDetails(reply)\"\n [attr.aria-label]=\"resolvedLabels.quickReplyDetails\"\n >\n info\n </mat-icon>\n }\n </span>\n }\n </span>\n @if (!isConversationQuickActionQuickReply(reply) && getQuickReplyContextChips(reply).length) {\n <span\n class=\"praxis-ai-assistant-shell__quick-reply-context\"\n >\n @for (chip of getQuickReplyContextChips(reply); track chip.ariaLabel + ':' + chip.value) {\n <span\n class=\"praxis-ai-assistant-shell__quick-reply-context-chip\"\n [attr.aria-label]=\"chip.ariaLabel\"\n >\n <mat-icon aria-hidden=\"true\">{{ chip.icon }}</mat-icon>\n <span>{{ chip.value }}</span>\n </span>\n }\n </span>\n }\n @if (!isConversationQuickActionQuickReply(reply) && getQuickReplyPresentationItems(reply).length) {\n <span\n class=\"praxis-ai-assistant-shell__quick-reply-insights\"\n >\n @for (item of getQuickReplyPresentationItems(reply); track item.key) {\n <span\n class=\"praxis-ai-assistant-shell__quick-reply-insight\"\n >\n <mat-icon aria-hidden=\"true\">{{ item.icon }}</mat-icon>\n <span class=\"praxis-ai-assistant-shell__quick-reply-insight-copy\">\n <span class=\"praxis-ai-assistant-shell__quick-reply-insight-label\">\n {{ item.label }}\n </span>\n <span class=\"praxis-ai-assistant-shell__quick-reply-insight-value\">\n {{ item.value }}\n </span>\n </span>\n </span>\n }\n </span>\n }\n @if (!isConversationQuickActionQuickReply(reply)) {\n <span class=\"praxis-ai-assistant-shell__quick-reply-cta\">\n {{ getQuickReplyCtaLabel(reply) }}\n <mat-icon aria-hidden=\"true\">arrow_forward</mat-icon>\n </span>\n }\n </span>\n </button>\n }\n </div>\n }\n @if (shouldShowStatusText()) {\n <p\n class=\"praxis-ai-assistant-shell__status\"\n [attr.data-testid]=\"testIdPrefix + '-status'\"\n >\n {{ getAuxiliaryStatusText() }}\n </p>\n }\n @if (shouldShowErrorText()) {\n <p\n class=\"praxis-ai-assistant-shell__error\"\n [attr.data-testid]=\"testIdPrefix + '-error'\"\n >\n {{ errorText }}\n </p>\n }\n </div>\n\n <footer class=\"praxis-ai-assistant-shell__footer\">\n <label class=\"praxis-ai-assistant-shell__label\" for=\"praxis-ai-assistant-shell-prompt\">\n {{ resolvedLabels.prompt }}\n </label>\n <div class=\"praxis-ai-assistant-shell__composer\">\n <textarea\n #promptInput\n id=\"praxis-ai-assistant-shell-prompt\"\n class=\"praxis-ai-assistant-shell__prompt\"\n rows=\"1\"\n [attr.data-testid]=\"testIdPrefix + '-prompt'\"\n [placeholder]=\"resolvedLabels.promptPlaceholder\"\n [ngModel]=\"currentPrompt\"\n [disabled]=\"busy\"\n (ngModelChange)=\"onPromptInput($event)\"\n (input)=\"resizePromptToContent()\"\n (keydown)=\"onPromptKeydown($event)\"\n (paste)=\"onPromptPaste($event)\"\n ></textarea>\n <div class=\"praxis-ai-assistant-shell__composer-actions\">\n @if (shouldShowVoiceInput()) {\n <button\n type=\"button\"\n [praxisIconButton]=\"isVoiceInputBusy() ? 'stop_circle' : 'mic'\"\n size=\"compact\"\n [pressed]=\"isVoiceInputBusy()\"\n class=\"praxis-ai-assistant-shell__voice-action\"\n [class.praxis-ai-assistant-shell__voice-action--active]=\"isVoiceInputBusy()\"\n [class.praxis-ai-assistant-shell__voice-action--error]=\"voiceCaptureState === 'error' || voiceCaptureState === 'unsupported'\"\n [disabled]=\"isVoiceInputDisabled()\"\n [matTooltip]=\"getVoiceActionLabel()\"\n [attr.aria-label]=\"getVoiceActionLabel()\"\n [attr.data-testid]=\"testIdPrefix + '-voice'\"\n (click)=\"onVoiceInputClick()\"\n ></button>\n }\n @if (showAttachAction) {\n <input\n #attachmentInput\n type=\"file\"\n hidden\n [attr.accept]=\"attachmentAccept || null\"\n [attr.multiple]=\"attachmentMultiple ? '' : null\"\n [attr.data-testid]=\"testIdPrefix + '-attachment-input'\"\n (change)=\"onAttachmentFilesSelected($event)\"\n >\n <button\n mat-stroked-button\n type=\"button\"\n [disabled]=\"busy\"\n (click)=\"onAttachClick(attachmentInput)\"\n [attr.data-testid]=\"testIdPrefix + '-attach'\"\n >\n <mat-icon>attach_file</mat-icon>\n {{ resolvedLabels.attach }}\n </button>\n }\n @if (getPrimaryAction().iconOnly) {\n <button\n type=\"button\"\n [praxisIconButton]=\"getPrimaryAction().icon || 'send'\"\n appearance=\"filled\"\n [ngClass]=\"'praxis-ai-assistant-shell__icon-action--tone-' + getShellActionTone(getPrimaryAction())\"\n [matTooltip]=\"getPrimaryActionTooltip(getPrimaryAction())\"\n [disabled]=\"isShellActionDisabled(getPrimaryAction())\"\n (click)=\"onShellAction(getPrimaryAction())\"\n [attr.data-testid]=\"getPrimaryAction().testId || (submitTestId || (testIdPrefix + '-submit'))\"\n [attr.aria-label]=\"getPrimaryAction().ariaLabel || getPrimaryAction().label\"\n ></button>\n } @else {\n <button\n mat-flat-button\n color=\"primary\"\n type=\"button\"\n class=\"praxis-ai-assistant-shell__action praxis-ai-assistant-shell__action--primary\"\n [matTooltip]=\"getPrimaryActionTooltip(getPrimaryAction())\"\n [ngClass]=\"'praxis-ai-assistant-shell__action--tone-' + getShellActionTone(getPrimaryAction())\"\n [disabled]=\"isShellActionDisabled(getPrimaryAction())\"\n (click)=\"onShellAction(getPrimaryAction())\"\n [attr.data-testid]=\"getPrimaryAction().testId || (submitTestId || (testIdPrefix + '-submit'))\"\n [attr.aria-label]=\"getPrimaryAction().ariaLabel || getPrimaryAction().label\"\n >\n @if (getPrimaryAction().icon) {\n <mat-icon aria-hidden=\"true\">{{ getPrimaryAction().icon }}</mat-icon>\n }\n <span>{{ getPrimaryAction().label }}</span>\n </button>\n }\n @for (action of getSecondaryActions(); track trackShellAction($index, action)) {\n <button\n mat-button\n type=\"button\"\n class=\"praxis-ai-assistant-shell__action praxis-ai-assistant-shell__action--secondary\"\n [ngClass]=\"'praxis-ai-assistant-shell__action--tone-' + getShellActionTone(action)\"\n [disabled]=\"isShellActionDisabled(action)\"\n (click)=\"onShellAction(action)\"\n [attr.data-testid]=\"action.testId || (testIdPrefix + '-action-' + action.id)\"\n [attr.aria-label]=\"action.ariaLabel || action.label\"\n >\n @if (action.icon) {\n <mat-icon aria-hidden=\"true\">{{ action.icon }}</mat-icon>\n }\n {{ action.label }}\n </button>\n }\n @if (busy) {\n <mat-spinner diameter=\"20\" [attr.data-testid]=\"testIdPrefix + '-spinner'\"></mat-spinner>\n }\n </div>\n @if (shouldShowVoiceFeedback()) {\n <p\n class=\"praxis-ai-assistant-shell__voice-status\"\n aria-live=\"polite\"\n [attr.data-testid]=\"testIdPrefix + '-voice-status'\"\n >\n {{ voiceFeedbackText }}\n </p>\n }\n </div>\n </footer>\n\n @if (resizable) {\n @for (direction of resizeHandles; track trackResizeHandle($index, direction)) {\n <span\n class=\"praxis-ai-assistant-shell__resize-handle praxis-ai-assistant-shell__resize-handle--{{ direction }}\"\n [attr.data-testid]=\"direction === 'se' ? testIdPrefix + '-resize-handle' : testIdPrefix + '-resize-handle-' + direction\"\n aria-hidden=\"true\"\n role=\"presentation\"\n (pointerdown)=\"startResize(direction, $event)\"\n ></span>\n }\n }\n</section>\n", styles: [":host{display:block;position:fixed;inset:0;z-index:var(--praxis-ai-assistant-shell-z-index, 1200);pointer-events:none}.praxis-ai-assistant-shell{--praxis-ai-assistant-shell-shadow-color: var(--md-sys-color-shadow);--praxis-ai-assistant-shell-highlight-color: var(--md-sys-color-on-surface);--praxis-ai-assistant-shell-tone-analytics: var(--md-sys-color-primary);--praxis-ai-assistant-shell-tone-resource: var(--md-sys-color-tertiary);--praxis-ai-assistant-shell-tone-success: var(--md-sys-color-tertiary);--praxis-ai-assistant-shell-tone-warning: var(--md-sys-color-secondary);--praxis-ai-assistant-shell-tone-danger: var(--md-sys-color-error);--praxis-ai-assistant-shell-tone-neutral: var(--md-sys-color-outline);position:fixed;box-sizing:border-box;min-width:0;min-height:0;display:flex;flex-direction:column;overflow:hidden;color:var(--md-sys-color-on-surface);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 70%,transparent);border-radius:8px;background:var(--md-sys-color-surface);box-shadow:0 24px 60px color-mix(in srgb,var(--praxis-ai-assistant-shell-shadow-color) 40%,transparent);pointer-events:auto;z-index:var(--praxis-ai-assistant-shell-z-index, 1200);container-type:inline-size}.praxis-ai-assistant-shell__header{flex:0 0 auto;display:flex;align-items:flex-start;gap:9px;padding:10px 10px 9px;border-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 72%,transparent);background:var(--md-sys-color-surface-container)}.praxis-ai-assistant-shell__header{justify-content:flex-start;border-bottom:1px solid;cursor:move;touch-action:none}.praxis-ai-assistant-shell__identity{flex:0 0 auto;display:grid;place-items:center;width:30px;height:30px;border-radius:8px;background:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary);box-shadow:0 6px 16px color-mix(in srgb,var(--md-sys-color-primary) 22%,transparent)}.praxis-ai-assistant-shell__identity mat-icon{width:18px;height:18px;font-size:18px}.praxis-ai-assistant-shell__title-group{min-width:0;flex:1 1 auto;display:grid;gap:4px}.praxis-ai-assistant-shell__title-row{min-width:0;display:flex;align-items:center;gap:8px}.praxis-ai-assistant-shell__badges{flex:0 0 auto;display:flex;align-items:center;justify-content:flex-end;gap:4px;min-width:0;flex-wrap:wrap}.praxis-ai-assistant-shell__badge{display:inline-flex;align-items:center;gap:5px;min-height:20px;max-width:120px;padding:2px 7px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 80%,transparent);border-radius:8px;color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container-high);font-size:11px;line-height:1.2;overflow-wrap:anywhere}.praxis-ai-assistant-shell__badge--context{color:var(--md-sys-color-on-surface);background:color-mix(in srgb,var(--md-sys-color-primary) 9%,var(--md-sys-color-surface-container-high))}.praxis-ai-assistant-shell__badge--state{border-color:transparent;background:transparent;color:var(--md-sys-color-on-surface-variant);padding-inline:3px}.praxis-ai-assistant-shell__badge--error{color:var(--md-sys-color-error);border-color:color-mix(in srgb,var(--md-sys-color-error) 60%,transparent)}.praxis-ai-assistant-shell__state-dot{flex:0 0 auto;width:6px;height:6px;border-radius:999px;background:var(--md-sys-color-primary);box-shadow:0 0 0 2px color-mix(in srgb,var(--md-sys-color-primary) 16%,transparent)}.praxis-ai-assistant-shell__badge--error .praxis-ai-assistant-shell__state-dot{background:var(--md-sys-color-error);box-shadow:0 0 0 2px color-mix(in srgb,var(--md-sys-color-error) 16%,transparent)}.praxis-ai-assistant-shell__title-group strong,.praxis-ai-assistant-shell__title-group p{min-width:0;margin:0;overflow-wrap:anywhere}.praxis-ai-assistant-shell__title-group strong{flex:1 1 auto;font-size:13px;line-height:1.2}.praxis-ai-assistant-shell__title-group p{color:var(--md-sys-color-on-surface-variant);font-size:11.5px;line-height:1.3}.praxis-ai-assistant-shell__header-actions{flex:0 0 auto;display:flex;align-items:center;gap:2px;margin-top:-3px}.praxis-ai-assistant-shell__header-actions .praxis-icon-button{color:var(--md-sys-color-on-surface-variant);opacity:.78}.praxis-ai-assistant-shell__header-actions .praxis-icon-button:hover,.praxis-ai-assistant-shell__header-actions .praxis-icon-button:focus-visible{opacity:1}.praxis-ai-assistant-shell__body{min-height:0;flex:1 1 auto;display:flex;flex-direction:column;gap:10px;padding:12px 12px 10px;overflow:auto;background:linear-gradient(180deg,var(--md-sys-color-surface-container-low),var(--md-sys-color-surface))}.praxis-ai-assistant-shell__context,.praxis-ai-assistant-shell__attachments{flex:0 0 auto;display:flex;align-items:center;gap:8px;overflow-x:auto;scrollbar-width:thin}.praxis-ai-assistant-shell__context-item{flex:0 0 auto;display:inline-flex;align-items:center;gap:5px;max-width:240px;padding:5px 8px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 70%,transparent);border-radius:8px;background:var(--md-sys-color-surface-container-high);font-size:12px;line-height:1.25}.praxis-ai-assistant-shell__context-item mat-icon{width:16px;height:16px;font-size:16px}.praxis-ai-assistant-shell__context-label,.praxis-ai-assistant-shell__context-value{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.praxis-ai-assistant-shell__context-label{color:var(--md-sys-color-on-surface)}.praxis-ai-assistant-shell__context-value{color:var(--md-sys-color-on-surface-variant)}.praxis-ai-assistant-shell__label{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.praxis-ai-assistant-shell__prompt{box-sizing:border-box;width:100%;min-height:48px;max-height:160px;resize:none;border:0;padding:12px 14px 4px;color:var(--md-sys-color-on-surface);background:transparent;font:inherit;line-height:1.45;outline:none;overflow-y:hidden;scrollbar-width:thin}.praxis-ai-assistant-shell__recommended{flex:0 0 auto;display:grid;gap:8px}.praxis-ai-assistant-shell__recommended-header{display:inline-flex;align-items:center;gap:6px;color:var(--md-sys-color-on-surface-variant);font-size:12px;font-weight:600;line-height:1.25}.praxis-ai-assistant-shell__recommended-header mat-icon{width:16px;height:16px;color:var(--md-sys-color-primary);font-size:16px;line-height:16px}.praxis-ai-assistant-shell__recommended-list{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,210px),1fr));gap:8px}.praxis-ai-assistant-shell__recommended-intent{--praxis-ai-assistant-shell-recommended-accent: var(--praxis-ai-assistant-shell-tone-neutral);appearance:none;border:1px solid color-mix(in srgb,var(--praxis-ai-assistant-shell-recommended-accent) 34%,transparent);border-radius:8px;background:linear-gradient(180deg,color-mix(in srgb,var(--praxis-ai-assistant-shell-recommended-accent) 8%,transparent),transparent),var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface);cursor:pointer;display:flex;gap:9px;min-width:0;min-height:86px;padding:10px;text-align:left;transition:border-color .16s ease,box-shadow .16s ease,background-color .16s ease}.praxis-ai-assistant-shell__recommended-intent:hover:not(:disabled),.praxis-ai-assistant-shell__recommended-intent:focus-visible{border-color:color-mix(in srgb,var(--praxis-ai-assistant-shell-recommended-accent) 68%,transparent);box-shadow:0 0 0 3px color-mix(in srgb,var(--praxis-ai-assistant-shell-recommended-accent) 15%,transparent);outline:none}.praxis-ai-assistant-shell__recommended-intent:disabled{cursor:default;opacity:.62}.praxis-ai-assistant-shell__recommended-icon{flex:0 0 auto;display:grid;place-items:center;width:30px;height:30px;border:1px solid color-mix(in srgb,var(--praxis-ai-assistant-shell-recommended-accent) 28%,transparent);border-radius:8px;background:color-mix(in srgb,var(--praxis-ai-assistant-shell-recommended-accent) 12%,transparent);color:var(--praxis-ai-assistant-shell-recommended-accent)}.praxis-ai-assistant-shell__recommended-icon mat-icon{width:18px;height:18px;font-size:18px;line-height:18px}.praxis-ai-assistant-shell__recommended-copy{min-width:0;display:grid;gap:5px}.praxis-ai-assistant-shell__recommended-title-row{min-width:0;display:flex;align-items:flex-start;justify-content:space-between;gap:8px}.praxis-ai-assistant-shell__recommended-title,.praxis-ai-assistant-shell__recommended-description,.praxis-ai-assistant-shell__recommended-group{min-width:0;overflow-wrap:anywhere}.praxis-ai-assistant-shell__recommended-title{color:var(--md-sys-color-on-surface);font-size:13px;font-weight:700;line-height:1.25}.praxis-ai-assistant-shell__recommended-group{flex:0 1 auto;max-width:44%;border-radius:8px;padding:2px 6px;background:color-mix(in srgb,var(--praxis-ai-assistant-shell-recommended-accent) 10%,transparent);color:color-mix(in srgb,var(--praxis-ai-assistant-shell-recommended-accent) 84%,var(--praxis-ai-assistant-shell-highlight-color));font-size:10.5px;font-weight:700;line-height:1.25}.praxis-ai-assistant-shell__recommended-description{color:var(--md-sys-color-on-surface-variant);font-size:12px;line-height:1.35}.praxis-ai-assistant-shell__recommended-cta{display:inline-flex;align-items:center;gap:5px;flex-wrap:wrap;color:color-mix(in srgb,var(--praxis-ai-assistant-shell-recommended-accent) 84%,var(--praxis-ai-assistant-shell-highlight-color));font-size:11.5px;font-weight:700;line-height:1.25}.praxis-ai-assistant-shell__recommended-cta mat-icon{width:15px;height:15px;font-size:15px;line-height:15px}.praxis-ai-assistant-shell__recommended-intent--tone-analytics{--praxis-ai-assistant-shell-recommended-accent: var(--praxis-ai-assistant-shell-tone-analytics)}.praxis-ai-assistant-shell__recommended-intent--tone-resource{--praxis-ai-assistant-shell-recommended-accent: var(--praxis-ai-assistant-shell-tone-resource)}.praxis-ai-assistant-shell__recommended-intent--tone-success{--praxis-ai-assistant-shell-recommended-accent: var(--praxis-ai-assistant-shell-tone-success)}.praxis-ai-assistant-shell__recommended-intent--tone-warning{--praxis-ai-assistant-shell-recommended-accent: var(--praxis-ai-assistant-shell-tone-warning)}.praxis-ai-assistant-shell__recommended-intent--tone-danger{--praxis-ai-assistant-shell-recommended-accent: var(--praxis-ai-assistant-shell-tone-danger)}.praxis-ai-assistant-shell__recommended-intent--tone-neutral{--praxis-ai-assistant-shell-recommended-accent: var(--praxis-ai-assistant-shell-tone-neutral)}.praxis-ai-assistant-shell__conversation{min-height:0;flex:1 1 auto;display:flex;flex-direction:column;gap:8px;overflow:auto;padding:2px}.praxis-ai-assistant-shell__message{max-width:86%;align-self:flex-start;padding:9px 11px;border-radius:8px;background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface);font-size:13px;line-height:1.35;overflow-wrap:anywhere}.praxis-ai-assistant-shell__message-content{white-space:normal}.praxis-ai-assistant-shell__message-content :where(p,ul,h3,h4,h5){margin:0}.praxis-ai-assistant-shell__message-content :where(p,ul,h3,h4,h5)+:where(p,ul,h3,h4,h5){margin-top:8px}.praxis-ai-assistant-shell__message-content ul,.praxis-ai-assistant-shell__message-content ol{margin:8px 0;padding-left:18px}.praxis-ai-assistant-shell__message-content li+li{margin-top:7px}.praxis-ai-assistant-shell__message-content code{padding:1px 4px;border-radius:4px;background:color-mix(in srgb,var(--md-sys-color-on-surface) 10%,transparent);font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:.94em}.praxis-ai-assistant-shell__assistant-content{display:grid;gap:8px}.praxis-ai-assistant-shell__assistant-block{display:grid;gap:8px;min-width:0}.praxis-ai-assistant-shell__assistant-block--summary,.praxis-ai-assistant-shell__assistant-block--recommendation{grid-template-columns:auto minmax(0,1fr);align-items:flex-start;padding:9px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 22%,transparent);border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-primary) 7%,transparent)}.praxis-ai-assistant-shell__assistant-block--recommendation{border-color:color-mix(in srgb,var(--praxis-ai-assistant-shell-tone-success) 26%,transparent);background:color-mix(in srgb,var(--praxis-ai-assistant-shell-tone-success) 8%,transparent)}.praxis-ai-assistant-shell__assistant-block-icon{display:grid;place-items:center;width:24px;height:24px;border-radius:8px;color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 14%,transparent)}.praxis-ai-assistant-shell__assistant-block--recommendation .praxis-ai-assistant-shell__assistant-block-icon{color:var(--praxis-ai-assistant-shell-tone-success);background:color-mix(in srgb,var(--praxis-ai-assistant-shell-tone-success) 14%,transparent)}.praxis-ai-assistant-shell__assistant-block-icon mat-icon{width:16px;height:16px;font-size:16px;line-height:16px}.praxis-ai-assistant-shell__assistant-block-copy{min-width:0}.praxis-ai-assistant-shell__assistant-block-copy strong{display:block;margin-bottom:3px}.praxis-ai-assistant-shell__assistant-block-heading{display:inline-flex;align-items:center;gap:6px;color:var(--md-sys-color-on-surface);font-size:12px;font-weight:700}.praxis-ai-assistant-shell__assistant-block-heading mat-icon{width:16px;height:16px;color:var(--md-sys-color-primary);font-size:16px}.praxis-ai-assistant-shell__assistant-resources{display:grid;gap:7px}.praxis-ai-assistant-shell__assistant-resource{display:grid;gap:7px;min-width:0;padding:9px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 76%,transparent);border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-surface-container-highest) 74%,transparent)}.praxis-ai-assistant-shell__assistant-resource-head{display:flex;align-items:flex-start;justify-content:space-between;gap:8px;min-width:0}.praxis-ai-assistant-shell__assistant-resource-head strong{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.praxis-ai-assistant-shell__assistant-resource-meta,.praxis-ai-assistant-shell__assistant-field-list,.praxis-ai-assistant-shell__assistant-evidence{display:flex;flex-wrap:wrap;gap:5px}.praxis-ai-assistant-shell__assistant-resource-meta span,.praxis-ai-assistant-shell__assistant-field,.praxis-ai-assistant-shell__assistant-evidence span{display:inline-flex;align-items:center;gap:4px;min-width:0;max-width:100%;padding:3px 6px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 62%,transparent);border-radius:999px;color:var(--md-sys-color-on-surface-variant);background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 82%,transparent);font-size:11px;line-height:1.25}.praxis-ai-assistant-shell__assistant-field{color:color-mix(in srgb,var(--md-sys-color-primary) 88%,var(--md-sys-color-on-surface));background:color-mix(in srgb,var(--md-sys-color-primary) 9%,transparent);border-color:color-mix(in srgb,var(--md-sys-color-primary) 22%,transparent)}.praxis-ai-assistant-shell__assistant-evidence span{color:color-mix(in srgb,var(--praxis-ai-assistant-shell-tone-success) 85%,var(--md-sys-color-on-surface));background:color-mix(in srgb,var(--praxis-ai-assistant-shell-tone-success) 9%,transparent);border-color:color-mix(in srgb,var(--praxis-ai-assistant-shell-tone-success) 22%,transparent)}.praxis-ai-assistant-shell__assistant-evidence mat-icon{width:13px;height:13px;font-size:13px}.praxis-ai-assistant-shell__assistant-resource p{margin:0;color:var(--md-sys-color-on-surface-variant)}.praxis-ai-assistant-shell__message-actions{display:flex;align-items:center;gap:4px;flex-wrap:wrap;margin-top:8px}.praxis-ai-assistant-shell__message-action:not(.praxis-icon-button){min-height:28px;padding:0 8px;border-radius:8px;font-size:12px}.praxis-ai-assistant-shell__message-action--icon{color:var(--md-sys-color-on-surface-variant)}.praxis-ai-assistant-shell__message-feedback,.praxis-ai-assistant-shell__message-feedback-submitted{display:flex;align-items:center;gap:4px;margin-top:8px}.praxis-ai-assistant-shell__message-feedback-action{color:var(--md-sys-color-on-surface-variant)}.praxis-ai-assistant-shell__message-feedback-submitted mat-icon{display:block;width:17px;height:17px;font-size:17px;line-height:17px}.praxis-ai-assistant-shell__message-feedback-submitted{color:var(--md-sys-color-on-surface-variant);font-size:12px}.praxis-ai-assistant-shell__message--assistant{border-bottom-left-radius:2px}.praxis-ai-assistant-shell__message--user{align-self:flex-end;border-bottom-right-radius:2px;background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}.praxis-ai-assistant-shell__message--status{color:var(--md-sys-color-on-surface-variant)}.praxis-ai-assistant-shell__message--error,.praxis-ai-assistant-shell__error{color:var(--md-sys-color-error)}.praxis-ai-assistant-shell__quick-replies{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,520px),1fr));gap:8px;align-items:stretch;padding-bottom:4px}.praxis-ai-assistant-shell__quick-replies--inline{display:flex;flex-wrap:wrap;align-items:center;gap:6px}.praxis-ai-assistant-shell__attachment{flex:0 0 auto;display:inline-flex;align-items:center;gap:7px;max-width:260px;min-height:34px;padding:4px 4px 4px 8px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 70%,transparent);border-radius:8px;background:var(--md-sys-color-surface-container-high)}.praxis-ai-assistant-shell__attachment--error{border-color:color-mix(in srgb,var(--md-sys-color-error) 60%,transparent)}.praxis-ai-assistant-shell__attachment-preview{flex:0 0 auto;width:28px;height:28px;border-radius:6px;object-fit:cover}.praxis-ai-assistant-shell__attachment-name,.praxis-ai-assistant-shell__attachment-kind{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:12px}.praxis-ai-assistant-shell__attachment-name{color:var(--md-sys-color-on-surface)}.praxis-ai-assistant-shell__attachment-kind{color:var(--md-sys-color-on-surface-variant)}.praxis-ai-assistant-shell__quick-reply{--praxis-ai-assistant-shell-quick-reply-accent: var(--md-sys-color-primary);--praxis-ai-assistant-shell-quick-reply-background: color-mix( in srgb, var(--praxis-ai-assistant-shell-quick-reply-accent) 7%, var(--md-sys-color-surface-container-high) );--praxis-ai-assistant-shell-quick-reply-foreground: var(--md-sys-color-on-surface);width:100%;max-width:100%;height:auto;min-height:0;position:relative;overflow:hidden;padding:15px 16px;align-items:stretch;border-color:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 36%,transparent);border-radius:22px;color:var(--praxis-ai-assistant-shell-quick-reply-foreground);background:linear-gradient(135deg,color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 16%,transparent),transparent 46%),radial-gradient(circle at 92% 10%,color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 22%,transparent),transparent 32%),var(--praxis-ai-assistant-shell-quick-reply-background);box-shadow:0 18px 42px color-mix(in srgb,var(--praxis-ai-assistant-shell-shadow-color) 22%,transparent),inset 0 1px color-mix(in srgb,var(--praxis-ai-assistant-shell-highlight-color) 16%,transparent);letter-spacing:normal;white-space:normal;text-align:left;text-transform:none;-webkit-user-select:none;user-select:none;transition:border-color .16s ease,box-shadow .16s ease,transform .16s ease,background .16s ease;--mdc-outlined-button-container-height: auto;--mat-outlined-button-horizontal-padding: 0}.praxis-ai-assistant-shell__quick-reply:hover:not(:disabled),.praxis-ai-assistant-shell__quick-reply:focus-visible{border-color:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 74%,transparent);box-shadow:0 18px 42px color-mix(in srgb,var(--praxis-ai-assistant-shell-shadow-color) 24%,transparent),0 0 0 3px color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 18%,transparent),inset 0 1px color-mix(in srgb,var(--praxis-ai-assistant-shell-highlight-color) 18%,transparent);transform:translateY(-1px)}.praxis-ai-assistant-shell__quick-reply--contextual-action{padding:10px 12px;border-color:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 34%,transparent);border-radius:8px;background:linear-gradient(90deg,color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 15%,transparent),color-mix(in srgb,var(--md-sys-color-surface-container-high) 92%,transparent)),var(--md-sys-color-surface-container-high);box-shadow:none}.praxis-ai-assistant-shell__quick-reply--guided-action{padding:10px 12px;border-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 82%,transparent);border-radius:8px;background:var(--md-sys-color-surface-container-high);box-shadow:none}.praxis-ai-assistant-shell__quick-reply--conversation-action{width:auto;min-width:0;padding:7px 11px;border-radius:999px;background:color-mix(in srgb,var(--md-sys-color-primary-container) 22%,var(--md-sys-color-surface-container-high));box-shadow:none}.praxis-ai-assistant-shell__quick-reply--conversation-action ::ng-deep .mdc-button__label{display:inline-flex;grid-template-columns:none;align-items:center;gap:7px}.praxis-ai-assistant-shell__quick-reply--conversation-action .praxis-ai-assistant-shell__quick-reply-icon-frame{width:22px;height:22px;border:0;background:transparent;box-shadow:none}.praxis-ai-assistant-shell__quick-reply--conversation-action .praxis-ai-assistant-shell__quick-reply-icon{width:17px;height:17px;font-size:17px}.praxis-ai-assistant-shell__quick-reply--conversation-action .praxis-ai-assistant-shell__quick-reply-copy,.praxis-ai-assistant-shell__quick-reply--conversation-action .praxis-ai-assistant-shell__quick-reply-heading{display:inline-flex;gap:0}.praxis-ai-assistant-shell__quick-reply--conversation-action .praxis-ai-assistant-shell__quick-reply-label{font-size:12.5px;font-weight:680;white-space:nowrap}.praxis-ai-assistant-shell__quick-reply--source-review{padding:11px 12px;border-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 88%,transparent);border-radius:8px;background:linear-gradient(90deg,color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 7%,transparent),transparent 58%),var(--md-sys-color-surface-container-high);box-shadow:none}.praxis-ai-assistant-shell__quick-reply--contextual-action:hover:not(:disabled),.praxis-ai-assistant-shell__quick-reply--contextual-action:focus-visible{border-color:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 62%,transparent);box-shadow:0 0 0 2px color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 15%,transparent);transform:none}.praxis-ai-assistant-shell__quick-reply--guided-action:hover:not(:disabled),.praxis-ai-assistant-shell__quick-reply--guided-action:focus-visible,.praxis-ai-assistant-shell__quick-reply--source-review:hover:not(:disabled),.praxis-ai-assistant-shell__quick-reply--source-review:focus-visible{border-color:color-mix(in srgb,var(--md-sys-color-primary) 64%,var(--md-sys-color-outline-variant));background:color-mix(in srgb,var(--md-sys-color-primary-container) 18%,var(--md-sys-color-surface-container-high));box-shadow:0 0 0 2px color-mix(in srgb,var(--md-sys-color-primary) 14%,transparent);transform:none}.praxis-ai-assistant-shell__quick-reply--contextual-action .praxis-ai-assistant-shell__quick-reply-ambient,.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-ambient,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-ambient{display:none}.praxis-ai-assistant-shell__quick-reply--contextual-action ::ng-deep .mdc-button__label,.praxis-ai-assistant-shell__quick-reply--guided-action ::ng-deep .mdc-button__label,.praxis-ai-assistant-shell__quick-reply--source-review ::ng-deep .mdc-button__label{gap:10px;align-items:flex-start}.praxis-ai-assistant-shell__quick-reply--contextual-action .praxis-ai-assistant-shell__quick-reply-icon-frame,.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-icon-frame,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-icon-frame{width:34px;height:34px;border-radius:8px;box-shadow:none}.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-icon-frame,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-icon-frame{border-color:color-mix(in srgb,var(--md-sys-color-primary) 24%,var(--md-sys-color-outline-variant));color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary-container) 34%,var(--md-sys-color-surface-container-high))}.praxis-ai-assistant-shell__quick-reply--contextual-action .praxis-ai-assistant-shell__quick-reply-icon,.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-icon,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-icon{width:19px;height:19px;font-size:19px}.praxis-ai-assistant-shell__quick-reply--contextual-action .praxis-ai-assistant-shell__quick-reply-copy,.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-copy,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-copy{gap:6px}.praxis-ai-assistant-shell__quick-reply--contextual-action .praxis-ai-assistant-shell__quick-reply-label,.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-label,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-label{font-size:13.5px;font-weight:760;letter-spacing:0}.praxis-ai-assistant-shell__quick-reply--contextual-action .praxis-ai-assistant-shell__quick-reply-description,.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-description,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-description{display:-webkit-box;overflow:hidden;font-size:12px;line-height:1.34;-webkit-box-orient:vertical;-webkit-line-clamp:2}.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-description{color:var(--md-sys-color-on-surface-variant)}.praxis-ai-assistant-shell__quick-reply--contextual-action .praxis-ai-assistant-shell__quick-reply-badge,.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-badge,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-badge{border-radius:8px;font-size:10px;letter-spacing:0}.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-badge,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-badge{border-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 76%,transparent);color:var(--md-sys-color-on-surface-variant);background:color-mix(in srgb,var(--md-sys-color-surface-container-lowest) 62%,transparent)}.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-cta,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-cta{color:var(--md-sys-color-primary)}.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-context{gap:5px}.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-context-chip{border-radius:8px;padding:4px 7px;background:color-mix(in srgb,var(--md-sys-color-surface-container-lowest) 66%,transparent);font-size:10.5px;font-weight:650}.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-actions{max-width:40%}.praxis-ai-assistant-shell__quick-reply--contextual-action .praxis-ai-assistant-shell__quick-reply-context-chip{border-radius:8px;padding:4px 7px;font-size:10.5px;font-weight:650}.praxis-ai-assistant-shell__quick-reply--contextual-action .praxis-ai-assistant-shell__quick-reply-cta,.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-cta,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-cta{font-size:11.5px}.praxis-ai-assistant-shell__quick-reply--compact{justify-self:start;width:fit-content;min-width:min(100%,210px);max-width:min(100%,320px);padding:9px 11px;border-radius:16px;background:linear-gradient(135deg,color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 10%,transparent),transparent 55%),var(--md-sys-color-surface-container-high);box-shadow:0 8px 18px color-mix(in srgb,var(--praxis-ai-assistant-shell-shadow-color) 16%,transparent),inset 0 1px color-mix(in srgb,var(--praxis-ai-assistant-shell-highlight-color) 10%,transparent)}.praxis-ai-assistant-shell__quick-reply.praxis-ai-assistant-shell__quick-reply--compact ::ng-deep .mdc-button__label{align-items:center;gap:10px}.praxis-ai-assistant-shell__quick-reply--compact .praxis-ai-assistant-shell__quick-reply-icon-frame{width:34px;height:34px;border-radius:12px}.praxis-ai-assistant-shell__quick-reply--compact .praxis-ai-assistant-shell__quick-reply-icon{width:19px;height:19px;font-size:19px}.praxis-ai-assistant-shell__quick-reply--compact .praxis-ai-assistant-shell__quick-reply-copy{gap:4px}.praxis-ai-assistant-shell__quick-reply--compact .praxis-ai-assistant-shell__quick-reply-header{align-items:center}.praxis-ai-assistant-shell__quick-reply--compact .praxis-ai-assistant-shell__quick-reply-label{font-size:13px;line-height:1.2}.praxis-ai-assistant-shell__quick-reply--compact .praxis-ai-assistant-shell__quick-reply-badge,.praxis-ai-assistant-shell__quick-reply--compact .praxis-ai-assistant-shell__quick-reply-cta{display:none}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply{width:auto;min-width:0;max-width:100%;padding:6px 10px;border-radius:999px;box-shadow:none}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply--guided-action{border-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 76%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container-high) 96%,transparent)}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply--guided-action:hover:not(:disabled),.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply--guided-action:focus-visible{border-color:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 52%,transparent);background:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 9%,var(--md-sys-color-surface-container-high));box-shadow:0 0 0 2px color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 12%,transparent)}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply ::ng-deep .mdc-button__label{display:inline-flex;grid-template-columns:none;align-items:center;gap:6px;width:auto}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply ::ng-deep .mat-mdc-button-touch-target{min-height:34px}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-icon-frame{width:18px;height:18px;border:0;border-radius:0;background:transparent;box-shadow:none}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-icon{width:16px;height:16px;color:var(--praxis-ai-assistant-shell-quick-reply-accent);font-size:16px}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-copy,.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-heading,.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-header{display:inline-flex;align-items:center;gap:0}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-label{color:var(--md-sys-color-on-surface);font-size:12.5px;font-weight:650;line-height:1.2;white-space:nowrap}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-description,.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-actions,.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-badge,.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-cta{display:none}.praxis-ai-assistant-shell__quick-reply ::ng-deep .mdc-button__label{position:relative;z-index:1;min-width:0;display:grid;grid-template-columns:auto minmax(0,1fr);align-items:flex-start;gap:14px;width:100%;height:auto;line-height:normal}.praxis-ai-assistant-shell__quick-reply-ambient{position:absolute;inset:0;pointer-events:none}.praxis-ai-assistant-shell__quick-reply-ambient:before{content:\"\";position:absolute;inset:0 18px auto;height:1px;border-radius:999px;background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 90%,var(--praxis-ai-assistant-shell-highlight-color)),transparent);opacity:.58}.praxis-ai-assistant-shell__quick-reply-ambient:after{content:\"\";position:absolute;top:-34px;right:-44px;width:150px;height:150px;border-radius:999px;background:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 13%,transparent);filter:blur(18px)}.praxis-ai-assistant-shell__quick-reply ::ng-deep .mat-mdc-button-touch-target{height:100%;min-height:48px}.praxis-ai-assistant-shell__quick-reply-icon-frame{flex:0 0 auto;width:46px;height:46px;display:inline-grid;place-items:center;border:1px solid color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 34%,transparent);border-radius:17px;color:var(--praxis-ai-assistant-shell-quick-reply-accent);background:linear-gradient(145deg,color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 24%,transparent),color-mix(in srgb,var(--praxis-ai-assistant-shell-highlight-color) 6%,transparent));box-shadow:inset 0 1px color-mix(in srgb,var(--praxis-ai-assistant-shell-highlight-color) 18%,transparent),0 10px 24px color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 12%,transparent)}.praxis-ai-assistant-shell__quick-reply-icon{width:24px;height:24px;font-size:24px}.praxis-ai-assistant-shell__quick-reply-details{flex:0 0 auto;width:24px;height:24px;display:inline-grid;place-items:center;border:1px solid color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 14%,transparent);border-radius:50%;color:var(--md-sys-color-on-surface-variant);background:color-mix(in srgb,var(--md-sys-color-outline) 14%,transparent);font-size:17px;opacity:.9}.praxis-ai-assistant-shell__quick-reply-copy{min-width:0;display:grid;gap:10px;flex:1 1 auto}.praxis-ai-assistant-shell__quick-reply-header{min-width:0;display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.praxis-ai-assistant-shell__quick-reply-heading{min-width:0;display:grid;gap:5px}.praxis-ai-assistant-shell__quick-reply-actions{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:flex-end;gap:7px;max-width:46%}.praxis-ai-assistant-shell__quick-reply-label,.praxis-ai-assistant-shell__quick-reply-description{min-width:0;overflow-wrap:anywhere}.praxis-ai-assistant-shell__quick-reply-label{color:var(--md-sys-color-on-surface);font-size:17px;font-weight:760;letter-spacing:.005em;line-height:1.18;text-transform:none}.praxis-ai-assistant-shell__quick-reply-badge{flex:0 0 auto;max-width:100%;padding:4px 8px;border:1px solid color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 28%,transparent);border-radius:999px;color:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 86%,var(--praxis-ai-assistant-shell-highlight-color));background:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 11%,transparent);font-size:10.5px;font-weight:700;letter-spacing:.02em;line-height:1.1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.praxis-ai-assistant-shell__quick-reply-description{color:color-mix(in srgb,var(--md-sys-color-on-surface) 80%,transparent);font-size:13px;line-height:1.46}.praxis-ai-assistant-shell__quick-reply-context{display:flex;flex-wrap:wrap;gap:7px;align-items:center}.praxis-ai-assistant-shell__quick-reply-context-chip{min-width:0;display:inline-flex;align-items:center;gap:4px;max-width:100%;padding:5px 8px;border:1px solid color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 22%,transparent);border-radius:999px;color:color-mix(in srgb,var(--md-sys-color-on-surface) 82%,transparent);background:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 9%,transparent);font-size:11px;font-weight:650;line-height:1.15}.praxis-ai-assistant-shell__quick-reply-context-chip mat-icon{width:14px;height:14px;color:var(--praxis-ai-assistant-shell-quick-reply-accent);font-size:14px}.praxis-ai-assistant-shell__quick-reply-context-chip span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.praxis-ai-assistant-shell__quick-reply-insights{display:grid;grid-template-columns:repeat(auto-fit,minmax(145px,1fr));gap:8px;padding:8px;border:1px solid color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 16%,transparent);border-radius:16px;background:linear-gradient(180deg,color-mix(in srgb,var(--praxis-ai-assistant-shell-highlight-color) 5%,transparent),color-mix(in srgb,var(--md-sys-color-surface-container-lowest) 26%,transparent))}.praxis-ai-assistant-shell__quick-reply-insight{min-width:0;display:grid;grid-template-columns:20px minmax(0,1fr);gap:8px;align-items:start;padding:8px;border:1px solid color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 10%,transparent);border-radius:13px;color:color-mix(in srgb,var(--md-sys-color-on-surface) 86%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container-high) 44%,transparent);font-size:12px;line-height:1.35}.praxis-ai-assistant-shell__quick-reply-insight mat-icon{width:17px;height:17px;color:var(--praxis-ai-assistant-shell-quick-reply-accent);font-size:17px;opacity:.9}.praxis-ai-assistant-shell__quick-reply-insight-copy{min-width:0;display:grid;gap:1px}.praxis-ai-assistant-shell__quick-reply-insight-label{color:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 82%,var(--praxis-ai-assistant-shell-highlight-color));font-size:10.5px;font-weight:760;letter-spacing:.045em;line-height:1.2;text-transform:uppercase}.praxis-ai-assistant-shell__quick-reply-insight-value{min-width:0;overflow-wrap:anywhere}.praxis-ai-assistant-shell__quick-reply-cta{display:inline-flex;align-items:center;justify-self:start;gap:5px;padding:3px 0;color:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 84%,var(--praxis-ai-assistant-shell-highlight-color));font-size:12px;font-weight:760;letter-spacing:.01em;line-height:1.2}.praxis-ai-assistant-shell__quick-reply-cta mat-icon{width:15px;height:15px;font-size:15px;transition:transform .16s ease}.praxis-ai-assistant-shell__quick-reply:hover:not(:disabled) .praxis-ai-assistant-shell__quick-reply-cta mat-icon,.praxis-ai-assistant-shell__quick-reply:focus-visible .praxis-ai-assistant-shell__quick-reply-cta mat-icon{transform:translate(2px)}.praxis-ai-assistant-shell__quick-reply--tone-analytics{--praxis-ai-assistant-shell-quick-reply-accent: var(--praxis-ai-assistant-shell-tone-analytics)}.praxis-ai-assistant-shell__quick-reply--tone-resource{--praxis-ai-assistant-shell-quick-reply-accent: var(--praxis-ai-assistant-shell-tone-resource)}.praxis-ai-assistant-shell__quick-reply--tone-warning{--praxis-ai-assistant-shell-quick-reply-accent: var(--praxis-ai-assistant-shell-tone-warning)}.praxis-ai-assistant-shell__quick-reply--tone-success{--praxis-ai-assistant-shell-quick-reply-accent: var(--praxis-ai-assistant-shell-tone-success)}.praxis-ai-assistant-shell__quick-reply--tone-danger{--praxis-ai-assistant-shell-quick-reply-accent: var(--praxis-ai-assistant-shell-tone-danger)}.praxis-ai-assistant-shell__quick-reply--tone-neutral{--praxis-ai-assistant-shell-quick-reply-accent: var(--praxis-ai-assistant-shell-tone-neutral)}@media(max-width:640px){.praxis-ai-assistant-shell__context{flex-wrap:wrap;overflow-x:visible}.praxis-ai-assistant-shell__context-item{max-width:min(100%,240px)}.praxis-ai-assistant-shell__quick-reply{padding:13px;border-radius:19px}.praxis-ai-assistant-shell__quick-reply ::ng-deep .mdc-button__label{grid-template-columns:minmax(0,1fr);gap:10px}.praxis-ai-assistant-shell__quick-reply-icon-frame{width:38px;height:38px;border-radius:14px}.praxis-ai-assistant-shell__quick-reply-header{display:grid}.praxis-ai-assistant-shell__quick-reply-actions{justify-content:flex-start;max-width:100%}.praxis-ai-assistant-shell__quick-reply-insights{grid-template-columns:minmax(0,1fr)}}@container (max-width: 400px){.praxis-ai-assistant-shell__header{display:grid;grid-template-columns:auto minmax(0,1fr) auto}.praxis-ai-assistant-shell__title-row{display:grid;gap:5px}.praxis-ai-assistant-shell__badges{justify-content:flex-start}.praxis-ai-assistant-shell__badge{max-width:100%}.praxis-ai-assistant-shell__context{flex-wrap:wrap;overflow-x:visible}.praxis-ai-assistant-shell__context-item{flex:1 1 150px;max-width:100%}.praxis-ai-assistant-shell__context-label,.praxis-ai-assistant-shell__context-value{overflow:visible;text-overflow:clip;white-space:normal;overflow-wrap:anywhere}.praxis-ai-assistant-shell__recommended-title-row,.praxis-ai-assistant-shell__assistant-resource-head{display:grid;justify-content:stretch}.praxis-ai-assistant-shell__recommended-group{max-width:100%;width:fit-content}.praxis-ai-assistant-shell__assistant-resource-head strong{overflow:visible;text-overflow:clip;white-space:normal;overflow-wrap:anywhere}}.praxis-ai-assistant-shell__status,.praxis-ai-assistant-shell__error{margin:0;font-size:13px;line-height:1.35;overflow-wrap:anywhere}.praxis-ai-assistant-shell__footer{flex:0 0 auto;padding:8px 10px 10px;border-top:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 72%,transparent);background:var(--md-sys-color-surface-container-low)}.praxis-ai-assistant-shell__composer{display:grid;gap:4px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container-lowest);box-shadow:inset 0 1px color-mix(in srgb,var(--praxis-ai-assistant-shell-highlight-color) 4%,transparent)}.praxis-ai-assistant-shell__composer:focus-within{border-color:var(--md-sys-color-primary);box-shadow:0 0 0 2px color-mix(in srgb,var(--md-sys-color-primary) 16%,transparent)}.praxis-ai-assistant-shell__composer-actions{display:flex;align-items:center;justify-content:flex-end;gap:4px;min-height:44px;padding:0 7px 6px;flex-wrap:nowrap}.praxis-ai-assistant-shell__voice-action{margin-right:auto;color:var(--md-sys-color-on-surface-variant)}.praxis-ai-assistant-shell__voice-action--active{color:var(--md-sys-color-error)}.praxis-ai-assistant-shell__voice-action--error{color:var(--praxis-ai-assistant-shell-tone-warning)}.praxis-ai-assistant-shell__icon-action--tone-governance,.praxis-ai-assistant-shell__icon-action--tone-primary{--praxis-icon-button-filled-background: var(--md-sys-color-primary);--praxis-icon-button-filled-foreground: var(--md-sys-color-on-primary)}.praxis-ai-assistant-shell__icon-action--tone-success{--praxis-icon-button-filled-background: var(--praxis-ai-assistant-shell-tone-success);--praxis-icon-button-filled-foreground: var(--md-sys-color-on-tertiary)}.praxis-ai-assistant-shell__icon-action--tone-warning{--praxis-icon-button-filled-background: var(--praxis-ai-assistant-shell-tone-warning);--praxis-icon-button-filled-foreground: var(--md-sys-color-on-secondary)}.praxis-ai-assistant-shell__icon-action--tone-danger{--praxis-icon-button-filled-background: var(--md-sys-color-error);--praxis-icon-button-filled-foreground: var(--md-sys-color-on-error)}.praxis-ai-assistant-shell__icon-action--tone-neutral,.praxis-ai-assistant-shell__icon-action--tone-secondary{--praxis-icon-button-filled-background: var(--md-sys-color-surface-variant);--praxis-icon-button-filled-foreground: var(--md-sys-color-on-surface-variant)}.praxis-ai-assistant-shell__voice-status{margin:-2px 10px 8px;color:var(--md-sys-color-on-surface-variant);font-size:12px;line-height:1.3}.praxis-ai-assistant-shell__action{min-height:36px;border-radius:10px;font-weight:650}.praxis-ai-assistant-shell__action mat-icon{width:18px;height:18px;margin-right:6px;font-size:18px}.praxis-ai-assistant-shell__action--secondary{color:var(--md-sys-color-on-surface-variant)}.praxis-ai-assistant-shell__action--tone-governance{color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 10%,transparent)}.praxis-ai-assistant-shell__action--tone-success{color:var(--praxis-ai-assistant-shell-tone-success);background:color-mix(in srgb,var(--praxis-ai-assistant-shell-tone-success) 10%,transparent)}.praxis-ai-assistant-shell__action--tone-warning{color:var(--praxis-ai-assistant-shell-tone-warning);background:color-mix(in srgb,var(--praxis-ai-assistant-shell-tone-warning) 10%,transparent)}.praxis-ai-assistant-shell__action--tone-danger{color:var(--md-sys-color-error);background:color-mix(in srgb,var(--md-sys-color-error) 10%,transparent)}.praxis-ai-assistant-shell__resize-handle{position:absolute;z-index:2;border:0;background:transparent;touch-action:none}.praxis-ai-assistant-shell__resize-handle--n,.praxis-ai-assistant-shell__resize-handle--s{left:16px;right:16px;height:10px;cursor:ns-resize}.praxis-ai-assistant-shell__resize-handle--n{top:-5px}.praxis-ai-assistant-shell__resize-handle--s{bottom:-5px}.praxis-ai-assistant-shell__resize-handle--e,.praxis-ai-assistant-shell__resize-handle--w{top:16px;bottom:16px;width:10px;cursor:ew-resize}.praxis-ai-assistant-shell__resize-handle--e{right:-5px}.praxis-ai-assistant-shell__resize-handle--w{left:-5px}.praxis-ai-assistant-shell__resize-handle--ne,.praxis-ai-assistant-shell__resize-handle--nw,.praxis-ai-assistant-shell__resize-handle--se,.praxis-ai-assistant-shell__resize-handle--sw{width:22px;height:22px}.praxis-ai-assistant-shell__resize-handle--ne{top:-5px;right:-5px;cursor:nesw-resize}.praxis-ai-assistant-shell__resize-handle--nw{top:-5px;left:-5px;cursor:nwse-resize}.praxis-ai-assistant-shell__resize-handle--se{right:-5px;bottom:-5px;cursor:nwse-resize}.praxis-ai-assistant-shell__resize-handle--sw{bottom:-5px;left:-5px;cursor:nesw-resize}.praxis-ai-assistant-shell__resize-handle--se:after{content:\"\";position:absolute;right:8px;bottom:8px;width:10px;height:10px;border-right:2px solid var(--md-sys-color-outline);border-bottom:2px solid var(--md-sys-color-outline)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.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: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i7.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i8.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
9657
9820
|
}
|
|
9658
9821
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisAiAssistantShellComponent, decorators: [{
|
|
9659
9822
|
type: Component,
|
|
@@ -9664,7 +9827,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
9664
9827
|
MatIconModule,
|
|
9665
9828
|
MatProgressSpinnerModule,
|
|
9666
9829
|
MatTooltipModule,
|
|
9667
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, providers: [PraxisBrowserSpeechTranscriptionService], template: "<section\n #panel\n class=\"praxis-ai-assistant-shell\"\n role=\"dialog\"\n [attr.aria-label]=\"resolvedLabels.title\"\n [attr.aria-busy]=\"busy ? 'true' : null\"\n [style.left.px]=\"currentLayout.left\"\n [style.top.px]=\"currentLayout.top\"\n [style.width.px]=\"currentLayout.width\"\n [style.height.px]=\"currentLayout.height\"\n [attr.data-testid]=\"panelTestId || testIdPrefix\"\n [attr.data-mode]=\"mode\"\n [attr.data-state]=\"state\"\n >\n <header\n class=\"praxis-ai-assistant-shell__header\"\n [attr.data-testid]=\"testIdPrefix + '-drag-handle'\"\n [attr.aria-label]=\"resolvedLabels.dragHandleAria\"\n (pointerdown)=\"startDrag($event)\"\n >\n <div class=\"praxis-ai-assistant-shell__identity\" aria-hidden=\"true\">\n <mat-icon>auto_awesome</mat-icon>\n </div>\n <div class=\"praxis-ai-assistant-shell__title-group\">\n <div class=\"praxis-ai-assistant-shell__title-row\">\n <strong>{{ resolvedLabels.title }}</strong>\n <div class=\"praxis-ai-assistant-shell__badges\" aria-hidden=\"true\">\n <span class=\"praxis-ai-assistant-shell__badge praxis-ai-assistant-shell__badge--context\">\n {{ getModeLabel() }}\n </span>\n <span\n class=\"praxis-ai-assistant-shell__badge praxis-ai-assistant-shell__badge--state\"\n [class.praxis-ai-assistant-shell__badge--error]=\"state === 'error'\"\n >\n <span class=\"praxis-ai-assistant-shell__state-dot\" aria-hidden=\"true\"></span>\n {{ getStateLabel() }}\n </span>\n </div>\n </div>\n @if (resolvedLabels.subtitle) {\n <p>{{ resolvedLabels.subtitle }}</p>\n }\n </div>\n <div class=\"praxis-ai-assistant-shell__header-actions\">\n <button\n mat-icon-button\n type=\"button\"\n [matTooltip]=\"resolvedLabels.close\"\n [attr.aria-label]=\"resolvedLabels.close\"\n (pointerdown)=\"$event.stopPropagation()\"\n (click)=\"close.emit()\"\n [attr.data-testid]=\"testIdPrefix + '-close'\"\n >\n <mat-icon>{{ getCloseIcon() }}</mat-icon>\n </button>\n </div>\n </header>\n\n <div class=\"praxis-ai-assistant-shell__body\">\n @if (contextItems.length) {\n <div\n class=\"praxis-ai-assistant-shell__context\"\n [attr.aria-label]=\"resolvedLabels.contextAria\"\n [attr.data-testid]=\"testIdPrefix + '-context'\"\n >\n @for (item of contextItems; track trackContextItem($index, item)) {\n <span\n class=\"praxis-ai-assistant-shell__context-item\"\n [attr.data-testid]=\"testIdPrefix + '-context-' + item.id\"\n >\n @if (item.icon) {\n <mat-icon aria-hidden=\"true\">{{ item.icon }}</mat-icon>\n }\n <span class=\"praxis-ai-assistant-shell__context-label\">{{ item.label }}</span>\n @if (item.value) {\n <span class=\"praxis-ai-assistant-shell__context-value\">{{ getContextItemValue(item) }}</span>\n }\n </span>\n }\n </div>\n }\n\n @if (shouldShowRecommendedIntents()) {\n <section\n class=\"praxis-ai-assistant-shell__recommended\"\n [attr.aria-label]=\"resolvedLabels.recommendedIntentsAria\"\n [attr.data-testid]=\"testIdPrefix + '-recommended-intents'\"\n >\n <div class=\"praxis-ai-assistant-shell__recommended-header\">\n <mat-icon aria-hidden=\"true\">auto_awesome</mat-icon>\n <span>{{ resolvedLabels.recommendedIntentsTitle }}</span>\n </div>\n <div class=\"praxis-ai-assistant-shell__recommended-list\">\n @for (intent of recommendedIntents; track trackRecommendedIntent($index, intent)) {\n <button\n type=\"button\"\n class=\"praxis-ai-assistant-shell__recommended-intent\"\n [ngClass]=\"'praxis-ai-assistant-shell__recommended-intent--tone-' + getRecommendedIntentTone(intent)\"\n [attr.data-testid]=\"testIdPrefix + '-recommended-intent-' + intent.id\"\n [attr.aria-label]=\"getRecommendedIntentAriaLabel(intent)\"\n [disabled]=\"isRecommendedIntentDisabled(intent)\"\n (click)=\"onRecommendedIntent(intent)\"\n >\n <span class=\"praxis-ai-assistant-shell__recommended-icon\" aria-hidden=\"true\">\n <mat-icon>{{ getRecommendedIntentIcon(intent) }}</mat-icon>\n </span>\n <span class=\"praxis-ai-assistant-shell__recommended-copy\">\n <span class=\"praxis-ai-assistant-shell__recommended-title-row\">\n <span class=\"praxis-ai-assistant-shell__recommended-title\">{{ intent.label }}</span>\n @if (getRecommendedIntentGroupLabel(intent)) {\n <span class=\"praxis-ai-assistant-shell__recommended-group\">\n {{ getRecommendedIntentGroupLabel(intent) }}\n </span>\n }\n </span>\n @if (getRecommendedIntentDescription(intent)) {\n <span class=\"praxis-ai-assistant-shell__recommended-description\">\n {{ getRecommendedIntentDescription(intent) }}\n </span>\n }\n <span class=\"praxis-ai-assistant-shell__recommended-cta\">\n @if (intent.requiresConfirmation && !intent.disabledReason) {\n <span>{{ resolvedLabels.recommendedIntentRequiresConfirmation }}</span>\n }\n <span>{{ getRecommendedIntentCtaLabel(intent) }}</span>\n <mat-icon aria-hidden=\"true\">arrow_forward</mat-icon>\n </span>\n </span>\n </button>\n }\n </div>\n </section>\n }\n\n <div\n #conversation\n class=\"praxis-ai-assistant-shell__conversation\"\n [attr.data-testid]=\"testIdPrefix + '-conversation'\"\n [attr.aria-label]=\"resolvedLabels.conversationAria\"\n >\n @if (!messages.length) {\n <article\n class=\"praxis-ai-assistant-shell__message praxis-ai-assistant-shell__message--assistant\"\n [attr.data-testid]=\"testIdPrefix + '-message-assistant-empty'\"\n >\n {{ resolvedLabels.emptyConversation }}\n </article>\n }\n @for (message of messages; track trackMessage($index, message)) {\n <article\n class=\"praxis-ai-assistant-shell__message\"\n [class.praxis-ai-assistant-shell__message--user]=\"message.role === 'user'\"\n [class.praxis-ai-assistant-shell__message--assistant]=\"message.role === 'assistant'\"\n [class.praxis-ai-assistant-shell__message--status]=\"message.role === 'status'\"\n [class.praxis-ai-assistant-shell__message--error]=\"message.role === 'error'\"\n [attr.data-testid]=\"testIdPrefix + '-message-' + message.role\"\n >\n <div\n class=\"praxis-ai-assistant-shell__message-content\"\n >\n @if (hasStructuredAssistantContent(message)) {\n <div class=\"praxis-ai-assistant-shell__assistant-content\">\n @for (block of getAssistantContentBlocks(message); track trackAssistantContentBlock($index, block)) {\n @switch (getAssistantContentBlockType(block)) {\n @case ('paragraph') {\n <section class=\"praxis-ai-assistant-shell__assistant-block praxis-ai-assistant-shell__assistant-block--summary\">\n <span class=\"praxis-ai-assistant-shell__assistant-block-icon\" aria-hidden=\"true\">\n <mat-icon>lightbulb</mat-icon>\n </span>\n <div\n class=\"praxis-ai-assistant-shell__assistant-block-copy\"\n [innerHTML]=\"renderMessageText(getAssistantContentBlockText(block))\"\n ></div>\n </section>\n }\n @case ('resource-list') {\n <section class=\"praxis-ai-assistant-shell__assistant-block\">\n <div class=\"praxis-ai-assistant-shell__assistant-block-heading\">\n <mat-icon aria-hidden=\"true\">database</mat-icon>\n <span>{{ getAssistantContentBlockTitle(block, 'Fontes confirmadas') }}</span>\n </div>\n <div class=\"praxis-ai-assistant-shell__assistant-resources\">\n @for (resource of getAssistantContentResources(block); track trackAssistantContentResource($index, resource)) {\n <article class=\"praxis-ai-assistant-shell__assistant-resource\">\n <div class=\"praxis-ai-assistant-shell__assistant-resource-head\">\n <strong>{{ resource.label }}</strong>\n @if (getAssistantContentResourceMeta(resource).length) {\n <span class=\"praxis-ai-assistant-shell__assistant-resource-meta\">\n @for (item of getAssistantContentResourceMeta(resource); track trackAssistantContentValue($index, item)) {\n <span>{{ item }}</span>\n }\n </span>\n }\n </div>\n @if (resource.description) {\n <p>{{ resource.description }}</p>\n }\n @if (resource.fields.length) {\n <div class=\"praxis-ai-assistant-shell__assistant-field-list\" aria-label=\"Campos dispon\u00EDveis\">\n @for (field of resource.fields; track trackAssistantContentField($index, field)) {\n <span\n class=\"praxis-ai-assistant-shell__assistant-field\"\n [matTooltip]=\"field.description || field.name\"\n >\n {{ field.label }}\n </span>\n }\n </div>\n }\n @if (resource.evidence.length) {\n <div class=\"praxis-ai-assistant-shell__assistant-evidence\" aria-label=\"Evid\u00EAncias\">\n @for (item of resource.evidence; track trackAssistantContentValue($index, item)) {\n <span>\n <mat-icon aria-hidden=\"true\">verified</mat-icon>\n {{ item }}\n </span>\n }\n </div>\n }\n </article>\n }\n </div>\n </section>\n }\n @case ('recommendation') {\n <section class=\"praxis-ai-assistant-shell__assistant-block praxis-ai-assistant-shell__assistant-block--recommendation\">\n <span class=\"praxis-ai-assistant-shell__assistant-block-icon\" aria-hidden=\"true\">\n <mat-icon>recommend</mat-icon>\n </span>\n <div class=\"praxis-ai-assistant-shell__assistant-block-copy\">\n <strong>{{ getAssistantContentBlockTitle(block, 'Recomenda\u00E7\u00E3o') }}</strong>\n <p>{{ getAssistantContentBlockText(block) }}</p>\n </div>\n </section>\n }\n }\n }\n </div>\n } @else {\n <div [innerHTML]=\"renderMessageText(message.text)\"></div>\n }\n </div>\n @if (message.actions?.length || message.editable || message.resendable) {\n <div\n class=\"praxis-ai-assistant-shell__message-actions\"\n >\n @if (message.editable) {\n <button\n mat-icon-button\n type=\"button\"\n class=\"praxis-ai-assistant-shell__message-action praxis-ai-assistant-shell__message-action--icon\"\n [disabled]=\"busy\"\n [matTooltip]=\"resolvedLabels.editMessage\"\n [attr.aria-label]=\"resolvedLabels.editMessage\"\n [attr.data-testid]=\"testIdPrefix + '-message-edit-' + message.id\"\n (click)=\"onMessageAction(message, { id: 'edit', label: resolvedLabels.editMessage, kind: 'edit' })\"\n >\n <mat-icon aria-hidden=\"true\">edit</mat-icon>\n </button>\n }\n @if (message.resendable) {\n <button\n mat-icon-button\n type=\"button\"\n class=\"praxis-ai-assistant-shell__message-action praxis-ai-assistant-shell__message-action--icon\"\n [disabled]=\"busy\"\n [matTooltip]=\"resolvedLabels.resendMessage\"\n [attr.aria-label]=\"resolvedLabels.resendMessage\"\n [attr.data-testid]=\"testIdPrefix + '-message-resend-' + message.id\"\n (click)=\"onMessageAction(message, { id: 'resend', label: resolvedLabels.resendMessage, kind: 'resend' })\"\n >\n <mat-icon aria-hidden=\"true\">replay</mat-icon>\n </button>\n }\n @for (action of message.actions || []; track trackMessageAction($index, action)) {\n @if (isMessageActionIconOnly(action)) {\n <button\n mat-icon-button\n type=\"button\"\n class=\"praxis-ai-assistant-shell__message-action praxis-ai-assistant-shell__message-action--icon\"\n [disabled]=\"busy || action.disabled\"\n [matTooltip]=\"getMessageActionLabel(action)\"\n [attr.aria-label]=\"getMessageActionLabel(action)\"\n [attr.data-testid]=\"testIdPrefix + '-message-action-' + message.id + '-' + action.id\"\n (click)=\"onMessageAction(message, action)\"\n >\n <mat-icon aria-hidden=\"true\">{{ getMessageActionIcon(action) }}</mat-icon>\n </button>\n } @else {\n <button\n mat-button\n type=\"button\"\n class=\"praxis-ai-assistant-shell__message-action\"\n [disabled]=\"busy || action.disabled\"\n [attr.aria-label]=\"getMessageActionLabel(action)\"\n [attr.data-testid]=\"testIdPrefix + '-message-action-' + message.id + '-' + action.id\"\n (click)=\"onMessageAction(message, action)\"\n >\n {{ action.label }}\n </button>\n }\n }\n </div>\n }\n @if (canSendMessageFeedback(message)) {\n <div class=\"praxis-ai-assistant-shell__message-feedback\">\n <button\n mat-icon-button\n type=\"button\"\n class=\"praxis-ai-assistant-shell__message-feedback-action\"\n [disabled]=\"busy\"\n [matTooltip]=\"resolvedLabels.feedbackPositive\"\n [attr.aria-label]=\"resolvedLabels.feedbackPositive\"\n [attr.data-testid]=\"testIdPrefix + '-message-feedback-positive-' + message.id\"\n (click)=\"sendMessageFeedback(message, 'positive')\"\n >\n <mat-icon aria-hidden=\"true\">thumb_up</mat-icon>\n </button>\n <button\n mat-icon-button\n type=\"button\"\n class=\"praxis-ai-assistant-shell__message-feedback-action\"\n [disabled]=\"busy\"\n [matTooltip]=\"resolvedLabels.feedbackNegative\"\n [attr.aria-label]=\"resolvedLabels.feedbackNegative\"\n [attr.data-testid]=\"testIdPrefix + '-message-feedback-negative-' + message.id\"\n (click)=\"sendMessageFeedback(message, 'negative')\"\n >\n <mat-icon aria-hidden=\"true\">thumb_down</mat-icon>\n </button>\n </div>\n } @else if (isMessageFeedbackSubmitted(message)) {\n <div\n class=\"praxis-ai-assistant-shell__message-feedback-submitted\"\n [attr.data-testid]=\"testIdPrefix + '-message-feedback-submitted-' + message.id\"\n >\n <mat-icon aria-hidden=\"true\">check</mat-icon>\n <span>{{ resolvedLabels.feedbackSubmitted }}</span>\n </div>\n }\n </article>\n }\n </div>\n\n @if (attachments.length) {\n <div\n class=\"praxis-ai-assistant-shell__attachments\"\n [attr.aria-label]=\"resolvedLabels.attachmentsAria\"\n [attr.data-testid]=\"testIdPrefix + '-attachments'\"\n >\n @for (attachment of attachments; track trackAttachment($index, attachment)) {\n <div\n class=\"praxis-ai-assistant-shell__attachment\"\n [class.praxis-ai-assistant-shell__attachment--error]=\"attachment.status === 'error'\"\n [attr.data-testid]=\"testIdPrefix + '-attachment-' + attachment.id\"\n >\n @if (attachment.previewUrl && attachment.kind === 'image') {\n <img\n class=\"praxis-ai-assistant-shell__attachment-preview\"\n [src]=\"attachment.previewUrl\"\n [alt]=\"attachment.name\"\n >\n }\n <span class=\"praxis-ai-assistant-shell__attachment-name\">{{ attachment.name }}</span>\n <span class=\"praxis-ai-assistant-shell__attachment-kind\">{{ attachment.kind }}</span>\n <button\n mat-icon-button\n type=\"button\"\n [disabled]=\"busy\"\n [matTooltip]=\"resolvedLabels.removeAttachment\"\n [attr.aria-label]=\"resolvedLabels.removeAttachment + ': ' + attachment.name\"\n [attr.data-testid]=\"testIdPrefix + '-attachment-remove-' + attachment.id\"\n (click)=\"onRemoveAttachment(attachment)\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </div>\n }\n </div>\n }\n\n @if (quickReplies.length) {\n <div\n class=\"praxis-ai-assistant-shell__quick-replies\"\n [class.praxis-ai-assistant-shell__quick-replies--inline]=\"shouldUseInlineQuickReplies()\"\n [attr.data-testid]=\"testIdPrefix + '-quick-replies'\"\n [attr.aria-label]=\"resolvedLabels.quickRepliesAria\"\n >\n @for (reply of quickReplies; track trackQuickReply($index, reply)) {\n <button\n mat-stroked-button\n type=\"button\"\n class=\"praxis-ai-assistant-shell__quick-reply\"\n [class.praxis-ai-assistant-shell__quick-reply--compact]=\"!isRichQuickReply(reply)\"\n [class.praxis-ai-assistant-shell__quick-reply--guided-action]=\"isGuidedActionQuickReply(reply)\"\n [class.praxis-ai-assistant-shell__quick-reply--contextual-action]=\"isContextualPreviewActionQuickReply(reply)\"\n [class.praxis-ai-assistant-shell__quick-reply--source-review]=\"isSourceReviewQuickReply(reply)\"\n [ngClass]=\"'praxis-ai-assistant-shell__quick-reply--tone-' + getQuickReplyTone(reply)\"\n [attr.data-testid]=\"testIdPrefix + '-quick-reply-' + (reply.id || reply.kind)\"\n [attr.aria-label]=\"getQuickReplyAriaLabel(reply)\"\n [disabled]=\"busy\"\n (click)=\"onQuickReply(reply)\"\n >\n <span class=\"praxis-ai-assistant-shell__quick-reply-ambient\" aria-hidden=\"true\"></span>\n <span class=\"praxis-ai-assistant-shell__quick-reply-icon-frame\" aria-hidden=\"true\">\n <mat-icon\n class=\"praxis-ai-assistant-shell__quick-reply-icon\"\n >\n {{ getQuickReplyIcon(reply) }}\n </mat-icon>\n </span>\n <span class=\"praxis-ai-assistant-shell__quick-reply-copy\">\n <span class=\"praxis-ai-assistant-shell__quick-reply-header\">\n <span class=\"praxis-ai-assistant-shell__quick-reply-heading\">\n <span class=\"praxis-ai-assistant-shell__quick-reply-label\">{{ getQuickReplyLabel(reply) }}</span>\n @if (getQuickReplyDescription(reply)) {\n <span\n class=\"praxis-ai-assistant-shell__quick-reply-description\"\n >\n {{ getQuickReplyDescription(reply) }}\n </span>\n }\n </span>\n <span class=\"praxis-ai-assistant-shell__quick-reply-actions\">\n <span class=\"praxis-ai-assistant-shell__quick-reply-badge\">\n {{ getQuickReplyCategoryLabel(reply) }}\n </span>\n @if (getQuickReplyTechnicalDetails(reply)) {\n <mat-icon\n class=\"praxis-ai-assistant-shell__quick-reply-details\"\n [matTooltip]=\"getQuickReplyTechnicalDetails(reply)\"\n [attr.aria-label]=\"resolvedLabels.quickReplyDetails\"\n >\n info\n </mat-icon>\n }\n </span>\n </span>\n @if (getQuickReplyContextChips(reply).length) {\n <span\n class=\"praxis-ai-assistant-shell__quick-reply-context\"\n >\n @for (chip of getQuickReplyContextChips(reply); track chip.ariaLabel + ':' + chip.value) {\n <span\n class=\"praxis-ai-assistant-shell__quick-reply-context-chip\"\n [attr.aria-label]=\"chip.ariaLabel\"\n >\n <mat-icon aria-hidden=\"true\">{{ chip.icon }}</mat-icon>\n <span>{{ chip.value }}</span>\n </span>\n }\n </span>\n }\n @if (getQuickReplyPresentationItems(reply).length) {\n <span\n class=\"praxis-ai-assistant-shell__quick-reply-insights\"\n >\n @for (item of getQuickReplyPresentationItems(reply); track item.key) {\n <span\n class=\"praxis-ai-assistant-shell__quick-reply-insight\"\n >\n <mat-icon aria-hidden=\"true\">{{ item.icon }}</mat-icon>\n <span class=\"praxis-ai-assistant-shell__quick-reply-insight-copy\">\n <span class=\"praxis-ai-assistant-shell__quick-reply-insight-label\">\n {{ item.label }}\n </span>\n <span class=\"praxis-ai-assistant-shell__quick-reply-insight-value\">\n {{ item.value }}\n </span>\n </span>\n </span>\n }\n </span>\n }\n <span class=\"praxis-ai-assistant-shell__quick-reply-cta\">\n {{ getQuickReplyCtaLabel(reply) }}\n <mat-icon aria-hidden=\"true\">arrow_forward</mat-icon>\n </span>\n </span>\n </button>\n }\n </div>\n }\n @if (shouldShowStatusText()) {\n <p\n class=\"praxis-ai-assistant-shell__status\"\n [attr.data-testid]=\"testIdPrefix + '-status'\"\n >\n {{ getAuxiliaryStatusText() }}\n </p>\n }\n @if (shouldShowErrorText()) {\n <p\n class=\"praxis-ai-assistant-shell__error\"\n [attr.data-testid]=\"testIdPrefix + '-error'\"\n >\n {{ errorText }}\n </p>\n }\n </div>\n\n <footer class=\"praxis-ai-assistant-shell__footer\">\n <label class=\"praxis-ai-assistant-shell__label\" for=\"praxis-ai-assistant-shell-prompt\">\n {{ resolvedLabels.prompt }}\n </label>\n <div class=\"praxis-ai-assistant-shell__composer\">\n <textarea\n #promptInput\n id=\"praxis-ai-assistant-shell-prompt\"\n class=\"praxis-ai-assistant-shell__prompt\"\n [attr.data-testid]=\"testIdPrefix + '-prompt'\"\n [placeholder]=\"resolvedLabels.promptPlaceholder\"\n [ngModel]=\"currentPrompt\"\n [disabled]=\"busy\"\n (ngModelChange)=\"onPromptInput($event)\"\n (keydown)=\"onPromptKeydown($event)\"\n (paste)=\"onPromptPaste($event)\"\n ></textarea>\n <div class=\"praxis-ai-assistant-shell__composer-actions\">\n @if (shouldShowVoiceInput()) {\n <button\n mat-icon-button\n type=\"button\"\n class=\"praxis-ai-assistant-shell__voice-action\"\n [class.praxis-ai-assistant-shell__voice-action--active]=\"isVoiceInputBusy()\"\n [class.praxis-ai-assistant-shell__voice-action--error]=\"voiceCaptureState === 'error' || voiceCaptureState === 'unsupported'\"\n [disabled]=\"isVoiceInputDisabled()\"\n [matTooltip]=\"getVoiceActionLabel()\"\n [attr.aria-label]=\"getVoiceActionLabel()\"\n [attr.aria-pressed]=\"isVoiceInputBusy() ? 'true' : 'false'\"\n [attr.data-testid]=\"testIdPrefix + '-voice'\"\n (click)=\"onVoiceInputClick()\"\n >\n <mat-icon aria-hidden=\"true\">{{ isVoiceInputBusy() ? 'stop_circle' : 'mic' }}</mat-icon>\n </button>\n }\n @if (showAttachAction) {\n <input\n #attachmentInput\n type=\"file\"\n hidden\n [attr.accept]=\"attachmentAccept || null\"\n [attr.multiple]=\"attachmentMultiple ? '' : null\"\n [attr.data-testid]=\"testIdPrefix + '-attachment-input'\"\n (change)=\"onAttachmentFilesSelected($event)\"\n >\n <button\n mat-stroked-button\n type=\"button\"\n [disabled]=\"busy\"\n (click)=\"onAttachClick(attachmentInput)\"\n [attr.data-testid]=\"testIdPrefix + '-attach'\"\n >\n <mat-icon>attach_file</mat-icon>\n {{ resolvedLabels.attach }}\n </button>\n }\n <button\n mat-flat-button\n color=\"primary\"\n type=\"button\"\n class=\"praxis-ai-assistant-shell__action praxis-ai-assistant-shell__action--primary\"\n [class.praxis-ai-assistant-shell__action--icon-only]=\"getPrimaryAction().iconOnly\"\n [matTooltip]=\"getPrimaryActionTooltip(getPrimaryAction())\"\n [ngClass]=\"'praxis-ai-assistant-shell__action--tone-' + getShellActionTone(getPrimaryAction())\"\n [disabled]=\"isShellActionDisabled(getPrimaryAction())\"\n (click)=\"onShellAction(getPrimaryAction())\"\n [attr.data-testid]=\"getPrimaryAction().testId || (submitTestId || (testIdPrefix + '-submit'))\"\n [attr.aria-label]=\"getPrimaryAction().ariaLabel || getPrimaryAction().label\"\n >\n @if (getPrimaryAction().icon) {\n <mat-icon aria-hidden=\"true\">{{ getPrimaryAction().icon }}</mat-icon>\n }\n @if (!getPrimaryAction().iconOnly) {\n <span>{{ getPrimaryAction().label }}</span>\n }\n </button>\n @for (action of getSecondaryActions(); track trackShellAction($index, action)) {\n <button\n mat-button\n type=\"button\"\n class=\"praxis-ai-assistant-shell__action praxis-ai-assistant-shell__action--secondary\"\n [ngClass]=\"'praxis-ai-assistant-shell__action--tone-' + getShellActionTone(action)\"\n [disabled]=\"isShellActionDisabled(action)\"\n (click)=\"onShellAction(action)\"\n [attr.data-testid]=\"action.testId || (testIdPrefix + '-action-' + action.id)\"\n [attr.aria-label]=\"action.ariaLabel || action.label\"\n >\n @if (action.icon) {\n <mat-icon aria-hidden=\"true\">{{ action.icon }}</mat-icon>\n }\n {{ action.label }}\n </button>\n }\n @if (busy) {\n <mat-spinner diameter=\"20\" [attr.data-testid]=\"testIdPrefix + '-spinner'\"></mat-spinner>\n }\n </div>\n @if (shouldShowVoiceFeedback()) {\n <p\n class=\"praxis-ai-assistant-shell__voice-status\"\n aria-live=\"polite\"\n [attr.data-testid]=\"testIdPrefix + '-voice-status'\"\n >\n {{ voiceFeedbackText }}\n </p>\n }\n </div>\n </footer>\n\n @if (resizable) {\n @for (direction of resizeHandles; track trackResizeHandle($index, direction)) {\n <span\n class=\"praxis-ai-assistant-shell__resize-handle praxis-ai-assistant-shell__resize-handle--{{ direction }}\"\n [attr.data-testid]=\"direction === 'se' ? testIdPrefix + '-resize-handle' : testIdPrefix + '-resize-handle-' + direction\"\n aria-hidden=\"true\"\n role=\"presentation\"\n (pointerdown)=\"startResize(direction, $event)\"\n ></span>\n }\n }\n</section>\n", styles: [":host{display:block;position:fixed;inset:0;z-index:var(--praxis-ai-assistant-shell-z-index, 1200);pointer-events:none}.praxis-ai-assistant-shell{--praxis-ai-assistant-shell-shadow-color: var(--md-sys-color-shadow);--praxis-ai-assistant-shell-highlight-color: var(--md-sys-color-on-surface);--praxis-ai-assistant-shell-tone-analytics: var(--md-sys-color-primary);--praxis-ai-assistant-shell-tone-resource: var(--md-sys-color-tertiary);--praxis-ai-assistant-shell-tone-success: var(--md-sys-color-tertiary);--praxis-ai-assistant-shell-tone-warning: var(--md-sys-color-secondary);--praxis-ai-assistant-shell-tone-danger: var(--md-sys-color-error);--praxis-ai-assistant-shell-tone-neutral: var(--md-sys-color-outline);position:fixed;box-sizing:border-box;min-width:0;min-height:0;display:flex;flex-direction:column;overflow:hidden;color:var(--md-sys-color-on-surface);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 70%,transparent);border-radius:8px;background:var(--md-sys-color-surface);box-shadow:0 24px 60px color-mix(in srgb,var(--praxis-ai-assistant-shell-shadow-color) 40%,transparent);pointer-events:auto;z-index:var(--praxis-ai-assistant-shell-z-index, 1200);container-type:inline-size}.praxis-ai-assistant-shell__header{flex:0 0 auto;display:flex;align-items:flex-start;gap:9px;padding:10px 10px 9px;border-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 72%,transparent);background:var(--md-sys-color-surface-container)}.praxis-ai-assistant-shell__header{justify-content:flex-start;border-bottom:1px solid;cursor:move;touch-action:none}.praxis-ai-assistant-shell__identity{flex:0 0 auto;display:grid;place-items:center;width:30px;height:30px;border-radius:8px;background:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary);box-shadow:0 6px 16px color-mix(in srgb,var(--md-sys-color-primary) 22%,transparent)}.praxis-ai-assistant-shell__identity mat-icon{width:18px;height:18px;font-size:18px}.praxis-ai-assistant-shell__title-group{min-width:0;flex:1 1 auto;display:grid;gap:4px}.praxis-ai-assistant-shell__title-row{min-width:0;display:flex;align-items:center;gap:8px}.praxis-ai-assistant-shell__badges{flex:0 0 auto;display:flex;align-items:center;justify-content:flex-end;gap:4px;min-width:0;flex-wrap:wrap}.praxis-ai-assistant-shell__badge{display:inline-flex;align-items:center;gap:5px;min-height:20px;max-width:120px;padding:2px 7px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 80%,transparent);border-radius:8px;color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container-high);font-size:11px;line-height:1.2;overflow-wrap:anywhere}.praxis-ai-assistant-shell__badge--context{color:var(--md-sys-color-on-surface);background:color-mix(in srgb,var(--md-sys-color-primary) 9%,var(--md-sys-color-surface-container-high))}.praxis-ai-assistant-shell__badge--state{border-color:transparent;background:transparent;color:var(--md-sys-color-on-surface-variant);padding-inline:3px}.praxis-ai-assistant-shell__badge--error{color:var(--md-sys-color-error);border-color:color-mix(in srgb,var(--md-sys-color-error) 60%,transparent)}.praxis-ai-assistant-shell__state-dot{flex:0 0 auto;width:6px;height:6px;border-radius:999px;background:var(--md-sys-color-primary);box-shadow:0 0 0 2px color-mix(in srgb,var(--md-sys-color-primary) 16%,transparent)}.praxis-ai-assistant-shell__badge--error .praxis-ai-assistant-shell__state-dot{background:var(--md-sys-color-error);box-shadow:0 0 0 2px color-mix(in srgb,var(--md-sys-color-error) 16%,transparent)}.praxis-ai-assistant-shell__title-group strong,.praxis-ai-assistant-shell__title-group p{min-width:0;margin:0;overflow-wrap:anywhere}.praxis-ai-assistant-shell__title-group strong{flex:1 1 auto;font-size:13px;line-height:1.2}.praxis-ai-assistant-shell__title-group p{color:var(--md-sys-color-on-surface-variant);font-size:11.5px;line-height:1.3}.praxis-ai-assistant-shell__header-actions{flex:0 0 auto;display:flex;align-items:center;gap:2px;margin-top:-3px}.praxis-ai-assistant-shell__header-actions button{display:inline-grid;place-items:center;width:34px;height:34px;padding:0;color:var(--md-sys-color-on-surface-variant);line-height:1;opacity:.78}.praxis-ai-assistant-shell__header-actions button:hover,.praxis-ai-assistant-shell__header-actions button:focus-visible{opacity:1}.praxis-ai-assistant-shell__header-actions mat-icon{display:block;width:18px;height:18px;font-size:18px;line-height:18px}.praxis-ai-assistant-shell__body{min-height:0;flex:1 1 auto;display:flex;flex-direction:column;gap:10px;padding:12px 12px 10px;overflow:auto;background:linear-gradient(180deg,var(--md-sys-color-surface-container-low),var(--md-sys-color-surface))}.praxis-ai-assistant-shell__context,.praxis-ai-assistant-shell__attachments{flex:0 0 auto;display:flex;align-items:center;gap:8px;overflow-x:auto;scrollbar-width:thin}.praxis-ai-assistant-shell__context-item{flex:0 0 auto;display:inline-flex;align-items:center;gap:5px;max-width:240px;padding:5px 8px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 70%,transparent);border-radius:8px;background:var(--md-sys-color-surface-container-high);font-size:12px;line-height:1.25}.praxis-ai-assistant-shell__context-item mat-icon{width:16px;height:16px;font-size:16px}.praxis-ai-assistant-shell__context-label,.praxis-ai-assistant-shell__context-value{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.praxis-ai-assistant-shell__context-label{color:var(--md-sys-color-on-surface)}.praxis-ai-assistant-shell__context-value{color:var(--md-sys-color-on-surface-variant)}.praxis-ai-assistant-shell__label{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.praxis-ai-assistant-shell__prompt{box-sizing:border-box;width:100%;min-height:46px;max-height:96px;resize:none;border:0;padding:10px 12px 8px;color:var(--md-sys-color-on-surface);background:transparent;font:inherit;line-height:1.45;outline:none}.praxis-ai-assistant-shell__recommended{flex:0 0 auto;display:grid;gap:8px}.praxis-ai-assistant-shell__recommended-header{display:inline-flex;align-items:center;gap:6px;color:var(--md-sys-color-on-surface-variant);font-size:12px;font-weight:600;line-height:1.25}.praxis-ai-assistant-shell__recommended-header mat-icon{width:16px;height:16px;color:var(--md-sys-color-primary);font-size:16px;line-height:16px}.praxis-ai-assistant-shell__recommended-list{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,210px),1fr));gap:8px}.praxis-ai-assistant-shell__recommended-intent{--praxis-ai-assistant-shell-recommended-accent: var(--praxis-ai-assistant-shell-tone-neutral);appearance:none;border:1px solid color-mix(in srgb,var(--praxis-ai-assistant-shell-recommended-accent) 34%,transparent);border-radius:8px;background:linear-gradient(180deg,color-mix(in srgb,var(--praxis-ai-assistant-shell-recommended-accent) 8%,transparent),transparent),var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface);cursor:pointer;display:flex;gap:9px;min-width:0;min-height:86px;padding:10px;text-align:left;transition:border-color .16s ease,box-shadow .16s ease,background-color .16s ease}.praxis-ai-assistant-shell__recommended-intent:hover:not(:disabled),.praxis-ai-assistant-shell__recommended-intent:focus-visible{border-color:color-mix(in srgb,var(--praxis-ai-assistant-shell-recommended-accent) 68%,transparent);box-shadow:0 0 0 3px color-mix(in srgb,var(--praxis-ai-assistant-shell-recommended-accent) 15%,transparent);outline:none}.praxis-ai-assistant-shell__recommended-intent:disabled{cursor:default;opacity:.62}.praxis-ai-assistant-shell__recommended-icon{flex:0 0 auto;display:grid;place-items:center;width:30px;height:30px;border:1px solid color-mix(in srgb,var(--praxis-ai-assistant-shell-recommended-accent) 28%,transparent);border-radius:8px;background:color-mix(in srgb,var(--praxis-ai-assistant-shell-recommended-accent) 12%,transparent);color:var(--praxis-ai-assistant-shell-recommended-accent)}.praxis-ai-assistant-shell__recommended-icon mat-icon{width:18px;height:18px;font-size:18px;line-height:18px}.praxis-ai-assistant-shell__recommended-copy{min-width:0;display:grid;gap:5px}.praxis-ai-assistant-shell__recommended-title-row{min-width:0;display:flex;align-items:flex-start;justify-content:space-between;gap:8px}.praxis-ai-assistant-shell__recommended-title,.praxis-ai-assistant-shell__recommended-description,.praxis-ai-assistant-shell__recommended-group{min-width:0;overflow-wrap:anywhere}.praxis-ai-assistant-shell__recommended-title{color:var(--md-sys-color-on-surface);font-size:13px;font-weight:700;line-height:1.25}.praxis-ai-assistant-shell__recommended-group{flex:0 1 auto;max-width:44%;border-radius:8px;padding:2px 6px;background:color-mix(in srgb,var(--praxis-ai-assistant-shell-recommended-accent) 10%,transparent);color:color-mix(in srgb,var(--praxis-ai-assistant-shell-recommended-accent) 84%,var(--praxis-ai-assistant-shell-highlight-color));font-size:10.5px;font-weight:700;line-height:1.25}.praxis-ai-assistant-shell__recommended-description{color:var(--md-sys-color-on-surface-variant);font-size:12px;line-height:1.35}.praxis-ai-assistant-shell__recommended-cta{display:inline-flex;align-items:center;gap:5px;flex-wrap:wrap;color:color-mix(in srgb,var(--praxis-ai-assistant-shell-recommended-accent) 84%,var(--praxis-ai-assistant-shell-highlight-color));font-size:11.5px;font-weight:700;line-height:1.25}.praxis-ai-assistant-shell__recommended-cta mat-icon{width:15px;height:15px;font-size:15px;line-height:15px}.praxis-ai-assistant-shell__recommended-intent--tone-analytics{--praxis-ai-assistant-shell-recommended-accent: var(--praxis-ai-assistant-shell-tone-analytics)}.praxis-ai-assistant-shell__recommended-intent--tone-resource{--praxis-ai-assistant-shell-recommended-accent: var(--praxis-ai-assistant-shell-tone-resource)}.praxis-ai-assistant-shell__recommended-intent--tone-success{--praxis-ai-assistant-shell-recommended-accent: var(--praxis-ai-assistant-shell-tone-success)}.praxis-ai-assistant-shell__recommended-intent--tone-warning{--praxis-ai-assistant-shell-recommended-accent: var(--praxis-ai-assistant-shell-tone-warning)}.praxis-ai-assistant-shell__recommended-intent--tone-danger{--praxis-ai-assistant-shell-recommended-accent: var(--praxis-ai-assistant-shell-tone-danger)}.praxis-ai-assistant-shell__recommended-intent--tone-neutral{--praxis-ai-assistant-shell-recommended-accent: var(--praxis-ai-assistant-shell-tone-neutral)}.praxis-ai-assistant-shell__conversation{min-height:0;flex:1 1 auto;display:flex;flex-direction:column;gap:8px;overflow:auto;padding:2px}.praxis-ai-assistant-shell__message{max-width:86%;align-self:flex-start;padding:9px 11px;border-radius:8px;background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface);font-size:13px;line-height:1.35;overflow-wrap:anywhere}.praxis-ai-assistant-shell__message-content{white-space:normal}.praxis-ai-assistant-shell__message-content :where(p,ul,h3,h4,h5){margin:0}.praxis-ai-assistant-shell__message-content :where(p,ul,h3,h4,h5)+:where(p,ul,h3,h4,h5){margin-top:8px}.praxis-ai-assistant-shell__message-content ul{padding-left:18px}.praxis-ai-assistant-shell__message-content li+li{margin-top:4px}.praxis-ai-assistant-shell__message-content code{padding:1px 4px;border-radius:4px;background:color-mix(in srgb,var(--md-sys-color-on-surface) 10%,transparent);font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:.94em}.praxis-ai-assistant-shell__assistant-content{display:grid;gap:8px}.praxis-ai-assistant-shell__assistant-block{display:grid;gap:8px;min-width:0}.praxis-ai-assistant-shell__assistant-block--summary,.praxis-ai-assistant-shell__assistant-block--recommendation{grid-template-columns:auto minmax(0,1fr);align-items:flex-start;padding:9px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 22%,transparent);border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-primary) 7%,transparent)}.praxis-ai-assistant-shell__assistant-block--recommendation{border-color:color-mix(in srgb,var(--praxis-ai-assistant-shell-tone-success) 26%,transparent);background:color-mix(in srgb,var(--praxis-ai-assistant-shell-tone-success) 8%,transparent)}.praxis-ai-assistant-shell__assistant-block-icon{display:grid;place-items:center;width:24px;height:24px;border-radius:8px;color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 14%,transparent)}.praxis-ai-assistant-shell__assistant-block--recommendation .praxis-ai-assistant-shell__assistant-block-icon{color:var(--praxis-ai-assistant-shell-tone-success);background:color-mix(in srgb,var(--praxis-ai-assistant-shell-tone-success) 14%,transparent)}.praxis-ai-assistant-shell__assistant-block-icon mat-icon{width:16px;height:16px;font-size:16px;line-height:16px}.praxis-ai-assistant-shell__assistant-block-copy{min-width:0}.praxis-ai-assistant-shell__assistant-block-copy strong{display:block;margin-bottom:3px}.praxis-ai-assistant-shell__assistant-block-heading{display:inline-flex;align-items:center;gap:6px;color:var(--md-sys-color-on-surface);font-size:12px;font-weight:700}.praxis-ai-assistant-shell__assistant-block-heading mat-icon{width:16px;height:16px;color:var(--md-sys-color-primary);font-size:16px}.praxis-ai-assistant-shell__assistant-resources{display:grid;gap:7px}.praxis-ai-assistant-shell__assistant-resource{display:grid;gap:7px;min-width:0;padding:9px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 76%,transparent);border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-surface-container-highest) 74%,transparent)}.praxis-ai-assistant-shell__assistant-resource-head{display:flex;align-items:flex-start;justify-content:space-between;gap:8px;min-width:0}.praxis-ai-assistant-shell__assistant-resource-head strong{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.praxis-ai-assistant-shell__assistant-resource-meta,.praxis-ai-assistant-shell__assistant-field-list,.praxis-ai-assistant-shell__assistant-evidence{display:flex;flex-wrap:wrap;gap:5px}.praxis-ai-assistant-shell__assistant-resource-meta span,.praxis-ai-assistant-shell__assistant-field,.praxis-ai-assistant-shell__assistant-evidence span{display:inline-flex;align-items:center;gap:4px;min-width:0;max-width:100%;padding:3px 6px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 62%,transparent);border-radius:999px;color:var(--md-sys-color-on-surface-variant);background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 82%,transparent);font-size:11px;line-height:1.25}.praxis-ai-assistant-shell__assistant-field{color:color-mix(in srgb,var(--md-sys-color-primary) 88%,var(--md-sys-color-on-surface));background:color-mix(in srgb,var(--md-sys-color-primary) 9%,transparent);border-color:color-mix(in srgb,var(--md-sys-color-primary) 22%,transparent)}.praxis-ai-assistant-shell__assistant-evidence span{color:color-mix(in srgb,var(--praxis-ai-assistant-shell-tone-success) 85%,var(--md-sys-color-on-surface));background:color-mix(in srgb,var(--praxis-ai-assistant-shell-tone-success) 9%,transparent);border-color:color-mix(in srgb,var(--praxis-ai-assistant-shell-tone-success) 22%,transparent)}.praxis-ai-assistant-shell__assistant-evidence mat-icon{width:13px;height:13px;font-size:13px}.praxis-ai-assistant-shell__assistant-resource p{margin:0;color:var(--md-sys-color-on-surface-variant)}.praxis-ai-assistant-shell__message-actions{display:flex;align-items:center;gap:4px;flex-wrap:wrap;margin-top:8px}.praxis-ai-assistant-shell__message-action{min-height:28px;padding:0 8px;border-radius:8px;font-size:12px}.praxis-ai-assistant-shell__message-action--icon{width:30px;min-width:30px;height:30px;padding:0;color:var(--md-sys-color-on-surface-variant)}.praxis-ai-assistant-shell__message-action--icon mat-icon{width:17px;height:17px;font-size:17px}.praxis-ai-assistant-shell__message-feedback,.praxis-ai-assistant-shell__message-feedback-submitted{display:flex;align-items:center;gap:4px;margin-top:8px}.praxis-ai-assistant-shell__message-feedback-action{--mdc-icon-button-state-layer-size: 30px;--mat-icon-button-state-layer-size: 30px;display:inline-grid;place-items:center;width:30px;min-width:30px;height:30px;padding:0;color:var(--md-sys-color-on-surface-variant);line-height:1}.praxis-ai-assistant-shell__message-feedback-action mat-icon,.praxis-ai-assistant-shell__message-feedback-submitted mat-icon{display:block;width:17px;height:17px;font-size:17px;line-height:17px}.praxis-ai-assistant-shell__message-feedback-submitted{color:var(--md-sys-color-on-surface-variant);font-size:12px}.praxis-ai-assistant-shell__message--assistant{border-bottom-left-radius:2px}.praxis-ai-assistant-shell__message--user{align-self:flex-end;border-bottom-right-radius:2px;background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}.praxis-ai-assistant-shell__message--status{color:var(--md-sys-color-on-surface-variant)}.praxis-ai-assistant-shell__message--error,.praxis-ai-assistant-shell__error{color:var(--md-sys-color-error)}.praxis-ai-assistant-shell__quick-replies{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,520px),1fr));gap:8px;align-items:stretch;padding-bottom:4px}.praxis-ai-assistant-shell__quick-replies--inline{display:flex;flex-wrap:wrap;align-items:center;gap:6px}.praxis-ai-assistant-shell__attachment{flex:0 0 auto;display:inline-flex;align-items:center;gap:7px;max-width:260px;min-height:34px;padding:4px 4px 4px 8px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 70%,transparent);border-radius:8px;background:var(--md-sys-color-surface-container-high)}.praxis-ai-assistant-shell__attachment--error{border-color:color-mix(in srgb,var(--md-sys-color-error) 60%,transparent)}.praxis-ai-assistant-shell__attachment-preview{flex:0 0 auto;width:28px;height:28px;border-radius:6px;object-fit:cover}.praxis-ai-assistant-shell__attachment-name,.praxis-ai-assistant-shell__attachment-kind{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:12px}.praxis-ai-assistant-shell__attachment-name{color:var(--md-sys-color-on-surface)}.praxis-ai-assistant-shell__attachment-kind{color:var(--md-sys-color-on-surface-variant)}.praxis-ai-assistant-shell__quick-reply{--praxis-ai-assistant-shell-quick-reply-accent: var(--md-sys-color-primary);--praxis-ai-assistant-shell-quick-reply-background: color-mix( in srgb, var(--praxis-ai-assistant-shell-quick-reply-accent) 7%, var(--md-sys-color-surface-container-high) );--praxis-ai-assistant-shell-quick-reply-foreground: var(--md-sys-color-on-surface);width:100%;max-width:100%;height:auto;min-height:0;position:relative;overflow:hidden;padding:15px 16px;align-items:stretch;border-color:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 36%,transparent);border-radius:22px;color:var(--praxis-ai-assistant-shell-quick-reply-foreground);background:linear-gradient(135deg,color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 16%,transparent),transparent 46%),radial-gradient(circle at 92% 10%,color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 22%,transparent),transparent 32%),var(--praxis-ai-assistant-shell-quick-reply-background);box-shadow:0 18px 42px color-mix(in srgb,var(--praxis-ai-assistant-shell-shadow-color) 22%,transparent),inset 0 1px color-mix(in srgb,var(--praxis-ai-assistant-shell-highlight-color) 16%,transparent);letter-spacing:normal;white-space:normal;text-align:left;text-transform:none;-webkit-user-select:none;user-select:none;transition:border-color .16s ease,box-shadow .16s ease,transform .16s ease,background .16s ease;--mdc-outlined-button-container-height: auto;--mat-outlined-button-horizontal-padding: 0}.praxis-ai-assistant-shell__quick-reply:hover:not(:disabled),.praxis-ai-assistant-shell__quick-reply:focus-visible{border-color:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 74%,transparent);box-shadow:0 18px 42px color-mix(in srgb,var(--praxis-ai-assistant-shell-shadow-color) 24%,transparent),0 0 0 3px color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 18%,transparent),inset 0 1px color-mix(in srgb,var(--praxis-ai-assistant-shell-highlight-color) 18%,transparent);transform:translateY(-1px)}.praxis-ai-assistant-shell__quick-reply--contextual-action{padding:10px 12px;border-color:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 34%,transparent);border-radius:8px;background:linear-gradient(90deg,color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 15%,transparent),color-mix(in srgb,var(--md-sys-color-surface-container-high) 92%,transparent)),var(--md-sys-color-surface-container-high);box-shadow:none}.praxis-ai-assistant-shell__quick-reply--guided-action{padding:10px 12px;border-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 82%,transparent);border-radius:8px;background:var(--md-sys-color-surface-container-high);box-shadow:none}.praxis-ai-assistant-shell__quick-reply--source-review{padding:11px 12px;border-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 88%,transparent);border-radius:8px;background:linear-gradient(90deg,color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 7%,transparent),transparent 58%),var(--md-sys-color-surface-container-high);box-shadow:none}.praxis-ai-assistant-shell__quick-reply--contextual-action:hover:not(:disabled),.praxis-ai-assistant-shell__quick-reply--contextual-action:focus-visible{border-color:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 62%,transparent);box-shadow:0 0 0 2px color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 15%,transparent);transform:none}.praxis-ai-assistant-shell__quick-reply--guided-action:hover:not(:disabled),.praxis-ai-assistant-shell__quick-reply--guided-action:focus-visible,.praxis-ai-assistant-shell__quick-reply--source-review:hover:not(:disabled),.praxis-ai-assistant-shell__quick-reply--source-review:focus-visible{border-color:color-mix(in srgb,var(--md-sys-color-primary) 64%,var(--md-sys-color-outline-variant));background:color-mix(in srgb,var(--md-sys-color-primary-container) 18%,var(--md-sys-color-surface-container-high));box-shadow:0 0 0 2px color-mix(in srgb,var(--md-sys-color-primary) 14%,transparent);transform:none}.praxis-ai-assistant-shell__quick-reply--contextual-action .praxis-ai-assistant-shell__quick-reply-ambient,.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-ambient,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-ambient{display:none}.praxis-ai-assistant-shell__quick-reply--contextual-action ::ng-deep .mdc-button__label,.praxis-ai-assistant-shell__quick-reply--guided-action ::ng-deep .mdc-button__label,.praxis-ai-assistant-shell__quick-reply--source-review ::ng-deep .mdc-button__label{gap:10px;align-items:flex-start}.praxis-ai-assistant-shell__quick-reply--contextual-action .praxis-ai-assistant-shell__quick-reply-icon-frame,.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-icon-frame,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-icon-frame{width:34px;height:34px;border-radius:8px;box-shadow:none}.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-icon-frame,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-icon-frame{border-color:color-mix(in srgb,var(--md-sys-color-primary) 24%,var(--md-sys-color-outline-variant));color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary-container) 34%,var(--md-sys-color-surface-container-high))}.praxis-ai-assistant-shell__quick-reply--contextual-action .praxis-ai-assistant-shell__quick-reply-icon,.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-icon,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-icon{width:19px;height:19px;font-size:19px}.praxis-ai-assistant-shell__quick-reply--contextual-action .praxis-ai-assistant-shell__quick-reply-copy,.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-copy,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-copy{gap:6px}.praxis-ai-assistant-shell__quick-reply--contextual-action .praxis-ai-assistant-shell__quick-reply-label,.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-label,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-label{font-size:13.5px;font-weight:760;letter-spacing:0}.praxis-ai-assistant-shell__quick-reply--contextual-action .praxis-ai-assistant-shell__quick-reply-description,.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-description,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-description{display:-webkit-box;overflow:hidden;font-size:12px;line-height:1.34;-webkit-box-orient:vertical;-webkit-line-clamp:2}.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-description{color:var(--md-sys-color-on-surface-variant)}.praxis-ai-assistant-shell__quick-reply--contextual-action .praxis-ai-assistant-shell__quick-reply-badge,.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-badge,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-badge{border-radius:8px;font-size:10px;letter-spacing:0}.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-badge,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-badge{border-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 76%,transparent);color:var(--md-sys-color-on-surface-variant);background:color-mix(in srgb,var(--md-sys-color-surface-container-lowest) 62%,transparent)}.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-cta,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-cta{color:var(--md-sys-color-primary)}.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-context{gap:5px}.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-context-chip{border-radius:8px;padding:4px 7px;background:color-mix(in srgb,var(--md-sys-color-surface-container-lowest) 66%,transparent);font-size:10.5px;font-weight:650}.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-actions{max-width:40%}.praxis-ai-assistant-shell__quick-reply--contextual-action .praxis-ai-assistant-shell__quick-reply-context-chip{border-radius:8px;padding:4px 7px;font-size:10.5px;font-weight:650}.praxis-ai-assistant-shell__quick-reply--contextual-action .praxis-ai-assistant-shell__quick-reply-cta,.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-cta,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-cta{font-size:11.5px}.praxis-ai-assistant-shell__quick-reply--compact{justify-self:start;width:fit-content;min-width:min(100%,210px);max-width:min(100%,320px);padding:9px 11px;border-radius:16px;background:linear-gradient(135deg,color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 10%,transparent),transparent 55%),var(--md-sys-color-surface-container-high);box-shadow:0 8px 18px color-mix(in srgb,var(--praxis-ai-assistant-shell-shadow-color) 16%,transparent),inset 0 1px color-mix(in srgb,var(--praxis-ai-assistant-shell-highlight-color) 10%,transparent)}.praxis-ai-assistant-shell__quick-reply.praxis-ai-assistant-shell__quick-reply--compact ::ng-deep .mdc-button__label{align-items:center;gap:10px}.praxis-ai-assistant-shell__quick-reply--compact .praxis-ai-assistant-shell__quick-reply-icon-frame{width:34px;height:34px;border-radius:12px}.praxis-ai-assistant-shell__quick-reply--compact .praxis-ai-assistant-shell__quick-reply-icon{width:19px;height:19px;font-size:19px}.praxis-ai-assistant-shell__quick-reply--compact .praxis-ai-assistant-shell__quick-reply-copy{gap:4px}.praxis-ai-assistant-shell__quick-reply--compact .praxis-ai-assistant-shell__quick-reply-header{align-items:center}.praxis-ai-assistant-shell__quick-reply--compact .praxis-ai-assistant-shell__quick-reply-label{font-size:13px;line-height:1.2}.praxis-ai-assistant-shell__quick-reply--compact .praxis-ai-assistant-shell__quick-reply-badge,.praxis-ai-assistant-shell__quick-reply--compact .praxis-ai-assistant-shell__quick-reply-cta{display:none}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply{width:auto;min-width:0;max-width:100%;padding:6px 10px;border-radius:999px;box-shadow:none}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply--guided-action{border-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 76%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container-high) 96%,transparent)}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply--guided-action:hover:not(:disabled),.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply--guided-action:focus-visible{border-color:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 52%,transparent);background:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 9%,var(--md-sys-color-surface-container-high));box-shadow:0 0 0 2px color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 12%,transparent)}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply ::ng-deep .mdc-button__label{display:inline-flex;grid-template-columns:none;align-items:center;gap:6px;width:auto}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply ::ng-deep .mat-mdc-button-touch-target{min-height:34px}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-icon-frame{width:18px;height:18px;border:0;border-radius:0;background:transparent;box-shadow:none}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-icon{width:16px;height:16px;color:var(--praxis-ai-assistant-shell-quick-reply-accent);font-size:16px}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-copy,.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-heading,.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-header{display:inline-flex;align-items:center;gap:0}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-label{color:var(--md-sys-color-on-surface);font-size:12.5px;font-weight:650;line-height:1.2;white-space:nowrap}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-description,.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-actions,.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-badge,.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-cta{display:none}.praxis-ai-assistant-shell__quick-reply ::ng-deep .mdc-button__label{position:relative;z-index:1;min-width:0;display:grid;grid-template-columns:auto minmax(0,1fr);align-items:flex-start;gap:14px;width:100%;height:auto;line-height:normal}.praxis-ai-assistant-shell__quick-reply-ambient{position:absolute;inset:0;pointer-events:none}.praxis-ai-assistant-shell__quick-reply-ambient:before{content:\"\";position:absolute;inset:0 18px auto;height:1px;border-radius:999px;background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 90%,var(--praxis-ai-assistant-shell-highlight-color)),transparent);opacity:.58}.praxis-ai-assistant-shell__quick-reply-ambient:after{content:\"\";position:absolute;top:-34px;right:-44px;width:150px;height:150px;border-radius:999px;background:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 13%,transparent);filter:blur(18px)}.praxis-ai-assistant-shell__quick-reply ::ng-deep .mat-mdc-button-touch-target{height:100%;min-height:48px}.praxis-ai-assistant-shell__quick-reply-icon-frame{flex:0 0 auto;width:46px;height:46px;display:inline-grid;place-items:center;border:1px solid color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 34%,transparent);border-radius:17px;color:var(--praxis-ai-assistant-shell-quick-reply-accent);background:linear-gradient(145deg,color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 24%,transparent),color-mix(in srgb,var(--praxis-ai-assistant-shell-highlight-color) 6%,transparent));box-shadow:inset 0 1px color-mix(in srgb,var(--praxis-ai-assistant-shell-highlight-color) 18%,transparent),0 10px 24px color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 12%,transparent)}.praxis-ai-assistant-shell__quick-reply-icon{width:24px;height:24px;font-size:24px}.praxis-ai-assistant-shell__quick-reply-details{flex:0 0 auto;width:24px;height:24px;display:inline-grid;place-items:center;border:1px solid color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 14%,transparent);border-radius:50%;color:var(--md-sys-color-on-surface-variant);background:color-mix(in srgb,var(--md-sys-color-outline) 14%,transparent);font-size:17px;opacity:.9}.praxis-ai-assistant-shell__quick-reply-copy{min-width:0;display:grid;gap:10px;flex:1 1 auto}.praxis-ai-assistant-shell__quick-reply-header{min-width:0;display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.praxis-ai-assistant-shell__quick-reply-heading{min-width:0;display:grid;gap:5px}.praxis-ai-assistant-shell__quick-reply-actions{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:flex-end;gap:7px;max-width:46%}.praxis-ai-assistant-shell__quick-reply-label,.praxis-ai-assistant-shell__quick-reply-description{min-width:0;overflow-wrap:anywhere}.praxis-ai-assistant-shell__quick-reply-label{color:var(--md-sys-color-on-surface);font-size:17px;font-weight:760;letter-spacing:.005em;line-height:1.18;text-transform:none}.praxis-ai-assistant-shell__quick-reply-badge{flex:0 0 auto;max-width:100%;padding:4px 8px;border:1px solid color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 28%,transparent);border-radius:999px;color:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 86%,var(--praxis-ai-assistant-shell-highlight-color));background:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 11%,transparent);font-size:10.5px;font-weight:700;letter-spacing:.02em;line-height:1.1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.praxis-ai-assistant-shell__quick-reply-description{color:color-mix(in srgb,var(--md-sys-color-on-surface) 80%,transparent);font-size:13px;line-height:1.46}.praxis-ai-assistant-shell__quick-reply-context{display:flex;flex-wrap:wrap;gap:7px;align-items:center}.praxis-ai-assistant-shell__quick-reply-context-chip{min-width:0;display:inline-flex;align-items:center;gap:4px;max-width:100%;padding:5px 8px;border:1px solid color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 22%,transparent);border-radius:999px;color:color-mix(in srgb,var(--md-sys-color-on-surface) 82%,transparent);background:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 9%,transparent);font-size:11px;font-weight:650;line-height:1.15}.praxis-ai-assistant-shell__quick-reply-context-chip mat-icon{width:14px;height:14px;color:var(--praxis-ai-assistant-shell-quick-reply-accent);font-size:14px}.praxis-ai-assistant-shell__quick-reply-context-chip span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.praxis-ai-assistant-shell__quick-reply-insights{display:grid;grid-template-columns:repeat(auto-fit,minmax(145px,1fr));gap:8px;padding:8px;border:1px solid color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 16%,transparent);border-radius:16px;background:linear-gradient(180deg,color-mix(in srgb,var(--praxis-ai-assistant-shell-highlight-color) 5%,transparent),color-mix(in srgb,var(--md-sys-color-surface-container-lowest) 26%,transparent))}.praxis-ai-assistant-shell__quick-reply-insight{min-width:0;display:grid;grid-template-columns:20px minmax(0,1fr);gap:8px;align-items:start;padding:8px;border:1px solid color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 10%,transparent);border-radius:13px;color:color-mix(in srgb,var(--md-sys-color-on-surface) 86%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container-high) 44%,transparent);font-size:12px;line-height:1.35}.praxis-ai-assistant-shell__quick-reply-insight mat-icon{width:17px;height:17px;color:var(--praxis-ai-assistant-shell-quick-reply-accent);font-size:17px;opacity:.9}.praxis-ai-assistant-shell__quick-reply-insight-copy{min-width:0;display:grid;gap:1px}.praxis-ai-assistant-shell__quick-reply-insight-label{color:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 82%,var(--praxis-ai-assistant-shell-highlight-color));font-size:10.5px;font-weight:760;letter-spacing:.045em;line-height:1.2;text-transform:uppercase}.praxis-ai-assistant-shell__quick-reply-insight-value{min-width:0;overflow-wrap:anywhere}.praxis-ai-assistant-shell__quick-reply-cta{display:inline-flex;align-items:center;justify-self:start;gap:5px;padding:3px 0;color:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 84%,var(--praxis-ai-assistant-shell-highlight-color));font-size:12px;font-weight:760;letter-spacing:.01em;line-height:1.2}.praxis-ai-assistant-shell__quick-reply-cta mat-icon{width:15px;height:15px;font-size:15px;transition:transform .16s ease}.praxis-ai-assistant-shell__quick-reply:hover:not(:disabled) .praxis-ai-assistant-shell__quick-reply-cta mat-icon,.praxis-ai-assistant-shell__quick-reply:focus-visible .praxis-ai-assistant-shell__quick-reply-cta mat-icon{transform:translate(2px)}.praxis-ai-assistant-shell__quick-reply--tone-analytics{--praxis-ai-assistant-shell-quick-reply-accent: var(--praxis-ai-assistant-shell-tone-analytics)}.praxis-ai-assistant-shell__quick-reply--tone-resource{--praxis-ai-assistant-shell-quick-reply-accent: var(--praxis-ai-assistant-shell-tone-resource)}.praxis-ai-assistant-shell__quick-reply--tone-warning{--praxis-ai-assistant-shell-quick-reply-accent: var(--praxis-ai-assistant-shell-tone-warning)}.praxis-ai-assistant-shell__quick-reply--tone-success{--praxis-ai-assistant-shell-quick-reply-accent: var(--praxis-ai-assistant-shell-tone-success)}.praxis-ai-assistant-shell__quick-reply--tone-danger{--praxis-ai-assistant-shell-quick-reply-accent: var(--praxis-ai-assistant-shell-tone-danger)}.praxis-ai-assistant-shell__quick-reply--tone-neutral{--praxis-ai-assistant-shell-quick-reply-accent: var(--praxis-ai-assistant-shell-tone-neutral)}@media(max-width:640px){.praxis-ai-assistant-shell__context{flex-wrap:wrap;overflow-x:visible}.praxis-ai-assistant-shell__context-item{max-width:min(100%,240px)}.praxis-ai-assistant-shell__quick-reply{padding:13px;border-radius:19px}.praxis-ai-assistant-shell__quick-reply ::ng-deep .mdc-button__label{grid-template-columns:minmax(0,1fr);gap:10px}.praxis-ai-assistant-shell__quick-reply-icon-frame{width:38px;height:38px;border-radius:14px}.praxis-ai-assistant-shell__quick-reply-header{display:grid}.praxis-ai-assistant-shell__quick-reply-actions{justify-content:flex-start;max-width:100%}.praxis-ai-assistant-shell__quick-reply-insights{grid-template-columns:minmax(0,1fr)}}@container (max-width: 400px){.praxis-ai-assistant-shell__header{display:grid;grid-template-columns:auto minmax(0,1fr) auto}.praxis-ai-assistant-shell__title-row{display:grid;gap:5px}.praxis-ai-assistant-shell__badges{justify-content:flex-start}.praxis-ai-assistant-shell__badge{max-width:100%}.praxis-ai-assistant-shell__context{flex-wrap:wrap;overflow-x:visible}.praxis-ai-assistant-shell__context-item{flex:1 1 150px;max-width:100%}.praxis-ai-assistant-shell__context-label,.praxis-ai-assistant-shell__context-value{overflow:visible;text-overflow:clip;white-space:normal;overflow-wrap:anywhere}.praxis-ai-assistant-shell__recommended-title-row,.praxis-ai-assistant-shell__assistant-resource-head{display:grid;justify-content:stretch}.praxis-ai-assistant-shell__recommended-group{max-width:100%;width:fit-content}.praxis-ai-assistant-shell__assistant-resource-head strong{overflow:visible;text-overflow:clip;white-space:normal;overflow-wrap:anywhere}}.praxis-ai-assistant-shell__status,.praxis-ai-assistant-shell__error{margin:0;font-size:13px;line-height:1.35;overflow-wrap:anywhere}.praxis-ai-assistant-shell__footer{flex:0 0 auto;padding:8px 10px 10px;border-top:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 72%,transparent);background:var(--md-sys-color-surface-container-low)}.praxis-ai-assistant-shell__composer{display:grid;gap:8px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container-lowest);box-shadow:inset 0 1px color-mix(in srgb,var(--praxis-ai-assistant-shell-highlight-color) 4%,transparent)}.praxis-ai-assistant-shell__composer:focus-within{border-color:var(--md-sys-color-primary);box-shadow:0 0 0 2px color-mix(in srgb,var(--md-sys-color-primary) 16%,transparent)}.praxis-ai-assistant-shell__composer-actions{display:flex;align-items:center;justify-content:flex-end;gap:8px;padding:0 8px 7px;flex-wrap:wrap}.praxis-ai-assistant-shell__voice-action{color:var(--md-sys-color-on-surface-variant)}.praxis-ai-assistant-shell__voice-action--active{color:var(--md-sys-color-error);background:color-mix(in srgb,var(--md-sys-color-error) 10%,transparent)}.praxis-ai-assistant-shell__voice-action--error{color:var(--praxis-ai-assistant-shell-tone-warning)}.praxis-ai-assistant-shell__voice-status{margin:-2px 10px 8px;color:var(--md-sys-color-on-surface-variant);font-size:12px;line-height:1.3}.praxis-ai-assistant-shell__action{min-height:36px;border-radius:10px;font-weight:650}.praxis-ai-assistant-shell__action mat-icon{width:18px;height:18px;margin-right:6px;font-size:18px}.praxis-ai-assistant-shell__action--icon-only{width:40px;min-width:40px;height:40px;padding-inline:0;border-radius:50%}.praxis-ai-assistant-shell__action--icon-only mat-icon{margin-right:0}.praxis-ai-assistant-shell__action--secondary{color:var(--md-sys-color-on-surface-variant)}.praxis-ai-assistant-shell__action--tone-governance{color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 10%,transparent)}.praxis-ai-assistant-shell__action--tone-success{color:var(--praxis-ai-assistant-shell-tone-success);background:color-mix(in srgb,var(--praxis-ai-assistant-shell-tone-success) 10%,transparent)}.praxis-ai-assistant-shell__action--tone-warning{color:var(--praxis-ai-assistant-shell-tone-warning);background:color-mix(in srgb,var(--praxis-ai-assistant-shell-tone-warning) 10%,transparent)}.praxis-ai-assistant-shell__action--tone-danger{color:var(--md-sys-color-error);background:color-mix(in srgb,var(--md-sys-color-error) 10%,transparent)}.praxis-ai-assistant-shell__resize-handle{position:absolute;z-index:2;border:0;background:transparent;touch-action:none}.praxis-ai-assistant-shell__resize-handle--n,.praxis-ai-assistant-shell__resize-handle--s{left:16px;right:16px;height:10px;cursor:ns-resize}.praxis-ai-assistant-shell__resize-handle--n{top:-5px}.praxis-ai-assistant-shell__resize-handle--s{bottom:-5px}.praxis-ai-assistant-shell__resize-handle--e,.praxis-ai-assistant-shell__resize-handle--w{top:16px;bottom:16px;width:10px;cursor:ew-resize}.praxis-ai-assistant-shell__resize-handle--e{right:-5px}.praxis-ai-assistant-shell__resize-handle--w{left:-5px}.praxis-ai-assistant-shell__resize-handle--ne,.praxis-ai-assistant-shell__resize-handle--nw,.praxis-ai-assistant-shell__resize-handle--se,.praxis-ai-assistant-shell__resize-handle--sw{width:22px;height:22px}.praxis-ai-assistant-shell__resize-handle--ne{top:-5px;right:-5px;cursor:nesw-resize}.praxis-ai-assistant-shell__resize-handle--nw{top:-5px;left:-5px;cursor:nwse-resize}.praxis-ai-assistant-shell__resize-handle--se{right:-5px;bottom:-5px;cursor:nwse-resize}.praxis-ai-assistant-shell__resize-handle--sw{bottom:-5px;left:-5px;cursor:nesw-resize}.praxis-ai-assistant-shell__resize-handle--se:after{content:\"\";position:absolute;right:8px;bottom:8px;width:10px;height:10px;border-right:2px solid var(--md-sys-color-outline);border-bottom:2px solid var(--md-sys-color-outline)}\n"] }]
|
|
9830
|
+
PraxisIconButtonComponent,
|
|
9831
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, providers: [PraxisBrowserSpeechTranscriptionService], template: "<section\n #panel\n class=\"praxis-ai-assistant-shell\"\n role=\"dialog\"\n [attr.aria-label]=\"resolvedLabels.title\"\n [attr.aria-busy]=\"busy ? 'true' : null\"\n [style.left.px]=\"currentLayout.left\"\n [style.top.px]=\"currentLayout.top\"\n [style.width.px]=\"currentLayout.width\"\n [style.height.px]=\"currentLayout.height\"\n [attr.data-testid]=\"panelTestId || testIdPrefix\"\n [attr.data-mode]=\"mode\"\n [attr.data-state]=\"state\"\n >\n <header\n class=\"praxis-ai-assistant-shell__header\"\n [attr.data-testid]=\"testIdPrefix + '-drag-handle'\"\n [attr.aria-label]=\"resolvedLabels.dragHandleAria\"\n (pointerdown)=\"startDrag($event)\"\n >\n <div class=\"praxis-ai-assistant-shell__identity\" aria-hidden=\"true\">\n <mat-icon>auto_awesome</mat-icon>\n </div>\n <div class=\"praxis-ai-assistant-shell__title-group\">\n <div class=\"praxis-ai-assistant-shell__title-row\">\n <strong>{{ resolvedLabels.title }}</strong>\n <div class=\"praxis-ai-assistant-shell__badges\" aria-hidden=\"true\">\n <span class=\"praxis-ai-assistant-shell__badge praxis-ai-assistant-shell__badge--context\">\n {{ getModeLabel() }}\n </span>\n <span\n class=\"praxis-ai-assistant-shell__badge praxis-ai-assistant-shell__badge--state\"\n [class.praxis-ai-assistant-shell__badge--error]=\"state === 'error'\"\n >\n <span class=\"praxis-ai-assistant-shell__state-dot\" aria-hidden=\"true\"></span>\n {{ getStateLabel() }}\n </span>\n </div>\n </div>\n @if (resolvedLabels.subtitle) {\n <p>{{ resolvedLabels.subtitle }}</p>\n }\n </div>\n <div class=\"praxis-ai-assistant-shell__header-actions\">\n <button\n [praxisIconButton]=\"getCloseIcon()\"\n size=\"compact\"\n type=\"button\"\n [matTooltip]=\"resolvedLabels.close\"\n [attr.aria-label]=\"resolvedLabels.close\"\n (pointerdown)=\"$event.stopPropagation()\"\n (click)=\"close.emit()\"\n [attr.data-testid]=\"testIdPrefix + '-close'\"\n ></button>\n </div>\n </header>\n\n <div class=\"praxis-ai-assistant-shell__body\">\n @if (contextItems.length) {\n <div\n class=\"praxis-ai-assistant-shell__context\"\n [attr.aria-label]=\"resolvedLabels.contextAria\"\n [attr.data-testid]=\"testIdPrefix + '-context'\"\n >\n @for (item of contextItems; track trackContextItem($index, item)) {\n <span\n class=\"praxis-ai-assistant-shell__context-item\"\n [attr.data-testid]=\"testIdPrefix + '-context-' + item.id\"\n >\n @if (item.icon) {\n <mat-icon aria-hidden=\"true\">{{ item.icon }}</mat-icon>\n }\n <span class=\"praxis-ai-assistant-shell__context-label\">{{ item.label }}</span>\n @if (item.value) {\n <span class=\"praxis-ai-assistant-shell__context-value\">{{ getContextItemValue(item) }}</span>\n }\n </span>\n }\n </div>\n }\n\n @if (shouldShowRecommendedIntents()) {\n <section\n class=\"praxis-ai-assistant-shell__recommended\"\n [attr.aria-label]=\"resolvedLabels.recommendedIntentsAria\"\n [attr.data-testid]=\"testIdPrefix + '-recommended-intents'\"\n >\n <div class=\"praxis-ai-assistant-shell__recommended-header\">\n <mat-icon aria-hidden=\"true\">auto_awesome</mat-icon>\n <span>{{ resolvedLabels.recommendedIntentsTitle }}</span>\n </div>\n <div class=\"praxis-ai-assistant-shell__recommended-list\">\n @for (intent of recommendedIntents; track trackRecommendedIntent($index, intent)) {\n <button\n type=\"button\"\n class=\"praxis-ai-assistant-shell__recommended-intent\"\n [ngClass]=\"'praxis-ai-assistant-shell__recommended-intent--tone-' + getRecommendedIntentTone(intent)\"\n [attr.data-testid]=\"testIdPrefix + '-recommended-intent-' + intent.id\"\n [attr.aria-label]=\"getRecommendedIntentAriaLabel(intent)\"\n [disabled]=\"isRecommendedIntentDisabled(intent)\"\n (click)=\"onRecommendedIntent(intent)\"\n >\n <span class=\"praxis-ai-assistant-shell__recommended-icon\" aria-hidden=\"true\">\n <mat-icon>{{ getRecommendedIntentIcon(intent) }}</mat-icon>\n </span>\n <span class=\"praxis-ai-assistant-shell__recommended-copy\">\n <span class=\"praxis-ai-assistant-shell__recommended-title-row\">\n <span class=\"praxis-ai-assistant-shell__recommended-title\">{{ intent.label }}</span>\n @if (getRecommendedIntentGroupLabel(intent)) {\n <span class=\"praxis-ai-assistant-shell__recommended-group\">\n {{ getRecommendedIntentGroupLabel(intent) }}\n </span>\n }\n </span>\n @if (getRecommendedIntentDescription(intent)) {\n <span class=\"praxis-ai-assistant-shell__recommended-description\">\n {{ getRecommendedIntentDescription(intent) }}\n </span>\n }\n <span class=\"praxis-ai-assistant-shell__recommended-cta\">\n @if (intent.requiresConfirmation && !intent.disabledReason) {\n <span>{{ resolvedLabels.recommendedIntentRequiresConfirmation }}</span>\n }\n <span>{{ getRecommendedIntentCtaLabel(intent) }}</span>\n <mat-icon aria-hidden=\"true\">arrow_forward</mat-icon>\n </span>\n </span>\n </button>\n }\n </div>\n </section>\n }\n\n <div\n #conversation\n class=\"praxis-ai-assistant-shell__conversation\"\n [attr.data-testid]=\"testIdPrefix + '-conversation'\"\n [attr.aria-label]=\"resolvedLabels.conversationAria\"\n >\n @if (!messages.length) {\n <article\n class=\"praxis-ai-assistant-shell__message praxis-ai-assistant-shell__message--assistant\"\n [attr.data-testid]=\"testIdPrefix + '-message-assistant-empty'\"\n >\n {{ resolvedLabels.emptyConversation }}\n </article>\n }\n @for (message of messages; track trackMessage($index, message)) {\n <article\n class=\"praxis-ai-assistant-shell__message\"\n [class.praxis-ai-assistant-shell__message--user]=\"message.role === 'user'\"\n [class.praxis-ai-assistant-shell__message--assistant]=\"message.role === 'assistant'\"\n [class.praxis-ai-assistant-shell__message--status]=\"message.role === 'status'\"\n [class.praxis-ai-assistant-shell__message--error]=\"message.role === 'error'\"\n [attr.data-testid]=\"testIdPrefix + '-message-' + message.role\"\n >\n <div\n class=\"praxis-ai-assistant-shell__message-content\"\n >\n @if (hasStructuredAssistantContent(message)) {\n <div class=\"praxis-ai-assistant-shell__assistant-content\">\n @for (block of getAssistantContentBlocks(message); track trackAssistantContentBlock($index, block)) {\n @switch (getAssistantContentBlockType(block)) {\n @case ('paragraph') {\n <section class=\"praxis-ai-assistant-shell__assistant-block praxis-ai-assistant-shell__assistant-block--summary\">\n <span class=\"praxis-ai-assistant-shell__assistant-block-icon\" aria-hidden=\"true\">\n <mat-icon>lightbulb</mat-icon>\n </span>\n <div\n class=\"praxis-ai-assistant-shell__assistant-block-copy\"\n [innerHTML]=\"renderMessageText(getAssistantContentBlockText(block))\"\n ></div>\n </section>\n }\n @case ('resource-list') {\n <section class=\"praxis-ai-assistant-shell__assistant-block\">\n <div class=\"praxis-ai-assistant-shell__assistant-block-heading\">\n <mat-icon aria-hidden=\"true\">database</mat-icon>\n <span>{{ getAssistantContentBlockTitle(block, 'Fontes confirmadas') }}</span>\n </div>\n <div class=\"praxis-ai-assistant-shell__assistant-resources\">\n @for (resource of getAssistantContentResources(block); track trackAssistantContentResource($index, resource)) {\n <article class=\"praxis-ai-assistant-shell__assistant-resource\">\n <div class=\"praxis-ai-assistant-shell__assistant-resource-head\">\n <strong>{{ resource.label }}</strong>\n @if (getAssistantContentResourceMeta(resource).length) {\n <span class=\"praxis-ai-assistant-shell__assistant-resource-meta\">\n @for (item of getAssistantContentResourceMeta(resource); track trackAssistantContentValue($index, item)) {\n <span>{{ item }}</span>\n }\n </span>\n }\n </div>\n @if (resource.description) {\n <p>{{ resource.description }}</p>\n }\n @if (resource.fields.length) {\n <div class=\"praxis-ai-assistant-shell__assistant-field-list\" aria-label=\"Campos dispon\u00EDveis\">\n @for (field of resource.fields; track trackAssistantContentField($index, field)) {\n <span\n class=\"praxis-ai-assistant-shell__assistant-field\"\n [matTooltip]=\"field.description || field.name\"\n >\n {{ field.label }}\n </span>\n }\n </div>\n }\n @if (resource.evidence.length) {\n <div class=\"praxis-ai-assistant-shell__assistant-evidence\" aria-label=\"Evid\u00EAncias\">\n @for (item of resource.evidence; track trackAssistantContentValue($index, item)) {\n <span>\n <mat-icon aria-hidden=\"true\">verified</mat-icon>\n {{ item }}\n </span>\n }\n </div>\n }\n </article>\n }\n </div>\n </section>\n }\n @case ('recommendation') {\n <section class=\"praxis-ai-assistant-shell__assistant-block praxis-ai-assistant-shell__assistant-block--recommendation\">\n <span class=\"praxis-ai-assistant-shell__assistant-block-icon\" aria-hidden=\"true\">\n <mat-icon>recommend</mat-icon>\n </span>\n <div class=\"praxis-ai-assistant-shell__assistant-block-copy\">\n <strong>{{ getAssistantContentBlockTitle(block, 'Recomenda\u00E7\u00E3o') }}</strong>\n <p>{{ getAssistantContentBlockText(block) }}</p>\n </div>\n </section>\n }\n }\n }\n </div>\n } @else {\n <div [innerHTML]=\"renderMessageText(message.text)\"></div>\n }\n </div>\n @if (message.actions?.length || message.editable || message.resendable) {\n <div\n class=\"praxis-ai-assistant-shell__message-actions\"\n >\n @if (message.editable) {\n <button\n praxisIconButton=\"edit\"\n size=\"dense\"\n type=\"button\"\n class=\"praxis-ai-assistant-shell__message-action praxis-ai-assistant-shell__message-action--icon\"\n [disabled]=\"busy\"\n [matTooltip]=\"resolvedLabels.editMessage\"\n [attr.aria-label]=\"resolvedLabels.editMessage\"\n [attr.data-testid]=\"testIdPrefix + '-message-edit-' + message.id\"\n (click)=\"onMessageAction(message, { id: 'edit', label: resolvedLabels.editMessage, kind: 'edit' })\"\n ></button>\n }\n @if (message.resendable) {\n <button\n praxisIconButton=\"replay\"\n size=\"dense\"\n type=\"button\"\n class=\"praxis-ai-assistant-shell__message-action praxis-ai-assistant-shell__message-action--icon\"\n [disabled]=\"busy\"\n [matTooltip]=\"resolvedLabels.resendMessage\"\n [attr.aria-label]=\"resolvedLabels.resendMessage\"\n [attr.data-testid]=\"testIdPrefix + '-message-resend-' + message.id\"\n (click)=\"onMessageAction(message, { id: 'resend', label: resolvedLabels.resendMessage, kind: 'resend' })\"\n ></button>\n }\n @for (action of message.actions || []; track trackMessageAction($index, action)) {\n @if (isMessageActionIconOnly(action)) {\n <button\n [praxisIconButton]=\"getMessageActionIcon(action)\"\n size=\"dense\"\n type=\"button\"\n class=\"praxis-ai-assistant-shell__message-action praxis-ai-assistant-shell__message-action--icon\"\n [disabled]=\"busy || action.disabled\"\n [matTooltip]=\"getMessageActionLabel(action)\"\n [attr.aria-label]=\"getMessageActionLabel(action)\"\n [attr.data-testid]=\"testIdPrefix + '-message-action-' + message.id + '-' + action.id\"\n (click)=\"onMessageAction(message, action)\"\n ></button>\n } @else {\n <button\n mat-button\n type=\"button\"\n class=\"praxis-ai-assistant-shell__message-action\"\n [disabled]=\"busy || action.disabled\"\n [attr.aria-label]=\"getMessageActionLabel(action)\"\n [attr.data-testid]=\"testIdPrefix + '-message-action-' + message.id + '-' + action.id\"\n (click)=\"onMessageAction(message, action)\"\n >\n {{ action.label }}\n </button>\n }\n }\n </div>\n }\n @if (canSendMessageFeedback(message)) {\n <div class=\"praxis-ai-assistant-shell__message-feedback\">\n <button\n praxisIconButton=\"thumb_up\"\n size=\"dense\"\n type=\"button\"\n class=\"praxis-ai-assistant-shell__message-feedback-action\"\n [disabled]=\"busy\"\n [matTooltip]=\"resolvedLabels.feedbackPositive\"\n [attr.aria-label]=\"resolvedLabels.feedbackPositive\"\n [attr.data-testid]=\"testIdPrefix + '-message-feedback-positive-' + message.id\"\n (click)=\"sendMessageFeedback(message, 'positive')\"\n ></button>\n <button\n praxisIconButton=\"thumb_down\"\n size=\"dense\"\n type=\"button\"\n class=\"praxis-ai-assistant-shell__message-feedback-action\"\n [disabled]=\"busy\"\n [matTooltip]=\"resolvedLabels.feedbackNegative\"\n [attr.aria-label]=\"resolvedLabels.feedbackNegative\"\n [attr.data-testid]=\"testIdPrefix + '-message-feedback-negative-' + message.id\"\n (click)=\"sendMessageFeedback(message, 'negative')\"\n ></button>\n </div>\n } @else if (isMessageFeedbackSubmitted(message)) {\n <div\n class=\"praxis-ai-assistant-shell__message-feedback-submitted\"\n [attr.data-testid]=\"testIdPrefix + '-message-feedback-submitted-' + message.id\"\n >\n <mat-icon aria-hidden=\"true\">check</mat-icon>\n <span>{{ resolvedLabels.feedbackSubmitted }}</span>\n </div>\n }\n </article>\n }\n </div>\n\n @if (attachments.length) {\n <div\n class=\"praxis-ai-assistant-shell__attachments\"\n [attr.aria-label]=\"resolvedLabels.attachmentsAria\"\n [attr.data-testid]=\"testIdPrefix + '-attachments'\"\n >\n @for (attachment of attachments; track trackAttachment($index, attachment)) {\n <div\n class=\"praxis-ai-assistant-shell__attachment\"\n [class.praxis-ai-assistant-shell__attachment--error]=\"attachment.status === 'error'\"\n [attr.data-testid]=\"testIdPrefix + '-attachment-' + attachment.id\"\n >\n @if (attachment.previewUrl && attachment.kind === 'image') {\n <img\n class=\"praxis-ai-assistant-shell__attachment-preview\"\n [src]=\"attachment.previewUrl\"\n [alt]=\"attachment.name\"\n >\n }\n <span class=\"praxis-ai-assistant-shell__attachment-name\">{{ attachment.name }}</span>\n <span class=\"praxis-ai-assistant-shell__attachment-kind\">{{ attachment.kind }}</span>\n <button\n praxisIconButton=\"close\"\n size=\"dense\"\n type=\"button\"\n [disabled]=\"busy\"\n [matTooltip]=\"resolvedLabels.removeAttachment\"\n [attr.aria-label]=\"resolvedLabels.removeAttachment + ': ' + attachment.name\"\n [attr.data-testid]=\"testIdPrefix + '-attachment-remove-' + attachment.id\"\n (click)=\"onRemoveAttachment(attachment)\"\n ></button>\n </div>\n }\n </div>\n }\n\n @if (quickReplies.length) {\n <div\n class=\"praxis-ai-assistant-shell__quick-replies\"\n [class.praxis-ai-assistant-shell__quick-replies--inline]=\"shouldUseInlineQuickReplies()\"\n [attr.data-testid]=\"testIdPrefix + '-quick-replies'\"\n [attr.aria-label]=\"resolvedLabels.quickRepliesAria\"\n >\n @for (reply of quickReplies; track trackQuickReply($index, reply)) {\n <button\n mat-stroked-button\n type=\"button\"\n class=\"praxis-ai-assistant-shell__quick-reply\"\n [class.praxis-ai-assistant-shell__quick-reply--compact]=\"!isRichQuickReply(reply)\"\n [class.praxis-ai-assistant-shell__quick-reply--guided-action]=\"isGuidedActionQuickReply(reply)\"\n [class.praxis-ai-assistant-shell__quick-reply--conversation-action]=\"isConversationQuickActionQuickReply(reply)\"\n [class.praxis-ai-assistant-shell__quick-reply--contextual-action]=\"isContextualPreviewActionQuickReply(reply)\"\n [class.praxis-ai-assistant-shell__quick-reply--source-review]=\"isSourceReviewQuickReply(reply)\"\n [ngClass]=\"'praxis-ai-assistant-shell__quick-reply--tone-' + getQuickReplyTone(reply)\"\n [attr.data-testid]=\"testIdPrefix + '-quick-reply-' + (reply.id || reply.kind)\"\n [attr.aria-label]=\"getQuickReplyAriaLabel(reply)\"\n [disabled]=\"busy\"\n (click)=\"onQuickReply(reply)\"\n >\n <span class=\"praxis-ai-assistant-shell__quick-reply-ambient\" aria-hidden=\"true\"></span>\n <span class=\"praxis-ai-assistant-shell__quick-reply-icon-frame\" aria-hidden=\"true\">\n <mat-icon\n class=\"praxis-ai-assistant-shell__quick-reply-icon\"\n >\n {{ getQuickReplyIcon(reply) }}\n </mat-icon>\n </span>\n <span class=\"praxis-ai-assistant-shell__quick-reply-copy\">\n <span class=\"praxis-ai-assistant-shell__quick-reply-header\">\n <span class=\"praxis-ai-assistant-shell__quick-reply-heading\">\n <span class=\"praxis-ai-assistant-shell__quick-reply-label\">{{ getQuickReplyLabel(reply) }}</span>\n @if (!isConversationQuickActionQuickReply(reply) && getQuickReplyDescription(reply)) {\n <span\n class=\"praxis-ai-assistant-shell__quick-reply-description\"\n >\n {{ getQuickReplyDescription(reply) }}\n </span>\n }\n </span>\n @if (!isConversationQuickActionQuickReply(reply)) {\n <span class=\"praxis-ai-assistant-shell__quick-reply-actions\">\n <span class=\"praxis-ai-assistant-shell__quick-reply-badge\">\n {{ getQuickReplyCategoryLabel(reply) }}\n </span>\n @if (getQuickReplyTechnicalDetails(reply)) {\n <mat-icon\n class=\"praxis-ai-assistant-shell__quick-reply-details\"\n [matTooltip]=\"getQuickReplyTechnicalDetails(reply)\"\n [attr.aria-label]=\"resolvedLabels.quickReplyDetails\"\n >\n info\n </mat-icon>\n }\n </span>\n }\n </span>\n @if (!isConversationQuickActionQuickReply(reply) && getQuickReplyContextChips(reply).length) {\n <span\n class=\"praxis-ai-assistant-shell__quick-reply-context\"\n >\n @for (chip of getQuickReplyContextChips(reply); track chip.ariaLabel + ':' + chip.value) {\n <span\n class=\"praxis-ai-assistant-shell__quick-reply-context-chip\"\n [attr.aria-label]=\"chip.ariaLabel\"\n >\n <mat-icon aria-hidden=\"true\">{{ chip.icon }}</mat-icon>\n <span>{{ chip.value }}</span>\n </span>\n }\n </span>\n }\n @if (!isConversationQuickActionQuickReply(reply) && getQuickReplyPresentationItems(reply).length) {\n <span\n class=\"praxis-ai-assistant-shell__quick-reply-insights\"\n >\n @for (item of getQuickReplyPresentationItems(reply); track item.key) {\n <span\n class=\"praxis-ai-assistant-shell__quick-reply-insight\"\n >\n <mat-icon aria-hidden=\"true\">{{ item.icon }}</mat-icon>\n <span class=\"praxis-ai-assistant-shell__quick-reply-insight-copy\">\n <span class=\"praxis-ai-assistant-shell__quick-reply-insight-label\">\n {{ item.label }}\n </span>\n <span class=\"praxis-ai-assistant-shell__quick-reply-insight-value\">\n {{ item.value }}\n </span>\n </span>\n </span>\n }\n </span>\n }\n @if (!isConversationQuickActionQuickReply(reply)) {\n <span class=\"praxis-ai-assistant-shell__quick-reply-cta\">\n {{ getQuickReplyCtaLabel(reply) }}\n <mat-icon aria-hidden=\"true\">arrow_forward</mat-icon>\n </span>\n }\n </span>\n </button>\n }\n </div>\n }\n @if (shouldShowStatusText()) {\n <p\n class=\"praxis-ai-assistant-shell__status\"\n [attr.data-testid]=\"testIdPrefix + '-status'\"\n >\n {{ getAuxiliaryStatusText() }}\n </p>\n }\n @if (shouldShowErrorText()) {\n <p\n class=\"praxis-ai-assistant-shell__error\"\n [attr.data-testid]=\"testIdPrefix + '-error'\"\n >\n {{ errorText }}\n </p>\n }\n </div>\n\n <footer class=\"praxis-ai-assistant-shell__footer\">\n <label class=\"praxis-ai-assistant-shell__label\" for=\"praxis-ai-assistant-shell-prompt\">\n {{ resolvedLabels.prompt }}\n </label>\n <div class=\"praxis-ai-assistant-shell__composer\">\n <textarea\n #promptInput\n id=\"praxis-ai-assistant-shell-prompt\"\n class=\"praxis-ai-assistant-shell__prompt\"\n rows=\"1\"\n [attr.data-testid]=\"testIdPrefix + '-prompt'\"\n [placeholder]=\"resolvedLabels.promptPlaceholder\"\n [ngModel]=\"currentPrompt\"\n [disabled]=\"busy\"\n (ngModelChange)=\"onPromptInput($event)\"\n (input)=\"resizePromptToContent()\"\n (keydown)=\"onPromptKeydown($event)\"\n (paste)=\"onPromptPaste($event)\"\n ></textarea>\n <div class=\"praxis-ai-assistant-shell__composer-actions\">\n @if (shouldShowVoiceInput()) {\n <button\n type=\"button\"\n [praxisIconButton]=\"isVoiceInputBusy() ? 'stop_circle' : 'mic'\"\n size=\"compact\"\n [pressed]=\"isVoiceInputBusy()\"\n class=\"praxis-ai-assistant-shell__voice-action\"\n [class.praxis-ai-assistant-shell__voice-action--active]=\"isVoiceInputBusy()\"\n [class.praxis-ai-assistant-shell__voice-action--error]=\"voiceCaptureState === 'error' || voiceCaptureState === 'unsupported'\"\n [disabled]=\"isVoiceInputDisabled()\"\n [matTooltip]=\"getVoiceActionLabel()\"\n [attr.aria-label]=\"getVoiceActionLabel()\"\n [attr.data-testid]=\"testIdPrefix + '-voice'\"\n (click)=\"onVoiceInputClick()\"\n ></button>\n }\n @if (showAttachAction) {\n <input\n #attachmentInput\n type=\"file\"\n hidden\n [attr.accept]=\"attachmentAccept || null\"\n [attr.multiple]=\"attachmentMultiple ? '' : null\"\n [attr.data-testid]=\"testIdPrefix + '-attachment-input'\"\n (change)=\"onAttachmentFilesSelected($event)\"\n >\n <button\n mat-stroked-button\n type=\"button\"\n [disabled]=\"busy\"\n (click)=\"onAttachClick(attachmentInput)\"\n [attr.data-testid]=\"testIdPrefix + '-attach'\"\n >\n <mat-icon>attach_file</mat-icon>\n {{ resolvedLabels.attach }}\n </button>\n }\n @if (getPrimaryAction().iconOnly) {\n <button\n type=\"button\"\n [praxisIconButton]=\"getPrimaryAction().icon || 'send'\"\n appearance=\"filled\"\n [ngClass]=\"'praxis-ai-assistant-shell__icon-action--tone-' + getShellActionTone(getPrimaryAction())\"\n [matTooltip]=\"getPrimaryActionTooltip(getPrimaryAction())\"\n [disabled]=\"isShellActionDisabled(getPrimaryAction())\"\n (click)=\"onShellAction(getPrimaryAction())\"\n [attr.data-testid]=\"getPrimaryAction().testId || (submitTestId || (testIdPrefix + '-submit'))\"\n [attr.aria-label]=\"getPrimaryAction().ariaLabel || getPrimaryAction().label\"\n ></button>\n } @else {\n <button\n mat-flat-button\n color=\"primary\"\n type=\"button\"\n class=\"praxis-ai-assistant-shell__action praxis-ai-assistant-shell__action--primary\"\n [matTooltip]=\"getPrimaryActionTooltip(getPrimaryAction())\"\n [ngClass]=\"'praxis-ai-assistant-shell__action--tone-' + getShellActionTone(getPrimaryAction())\"\n [disabled]=\"isShellActionDisabled(getPrimaryAction())\"\n (click)=\"onShellAction(getPrimaryAction())\"\n [attr.data-testid]=\"getPrimaryAction().testId || (submitTestId || (testIdPrefix + '-submit'))\"\n [attr.aria-label]=\"getPrimaryAction().ariaLabel || getPrimaryAction().label\"\n >\n @if (getPrimaryAction().icon) {\n <mat-icon aria-hidden=\"true\">{{ getPrimaryAction().icon }}</mat-icon>\n }\n <span>{{ getPrimaryAction().label }}</span>\n </button>\n }\n @for (action of getSecondaryActions(); track trackShellAction($index, action)) {\n <button\n mat-button\n type=\"button\"\n class=\"praxis-ai-assistant-shell__action praxis-ai-assistant-shell__action--secondary\"\n [ngClass]=\"'praxis-ai-assistant-shell__action--tone-' + getShellActionTone(action)\"\n [disabled]=\"isShellActionDisabled(action)\"\n (click)=\"onShellAction(action)\"\n [attr.data-testid]=\"action.testId || (testIdPrefix + '-action-' + action.id)\"\n [attr.aria-label]=\"action.ariaLabel || action.label\"\n >\n @if (action.icon) {\n <mat-icon aria-hidden=\"true\">{{ action.icon }}</mat-icon>\n }\n {{ action.label }}\n </button>\n }\n @if (busy) {\n <mat-spinner diameter=\"20\" [attr.data-testid]=\"testIdPrefix + '-spinner'\"></mat-spinner>\n }\n </div>\n @if (shouldShowVoiceFeedback()) {\n <p\n class=\"praxis-ai-assistant-shell__voice-status\"\n aria-live=\"polite\"\n [attr.data-testid]=\"testIdPrefix + '-voice-status'\"\n >\n {{ voiceFeedbackText }}\n </p>\n }\n </div>\n </footer>\n\n @if (resizable) {\n @for (direction of resizeHandles; track trackResizeHandle($index, direction)) {\n <span\n class=\"praxis-ai-assistant-shell__resize-handle praxis-ai-assistant-shell__resize-handle--{{ direction }}\"\n [attr.data-testid]=\"direction === 'se' ? testIdPrefix + '-resize-handle' : testIdPrefix + '-resize-handle-' + direction\"\n aria-hidden=\"true\"\n role=\"presentation\"\n (pointerdown)=\"startResize(direction, $event)\"\n ></span>\n }\n }\n</section>\n", styles: [":host{display:block;position:fixed;inset:0;z-index:var(--praxis-ai-assistant-shell-z-index, 1200);pointer-events:none}.praxis-ai-assistant-shell{--praxis-ai-assistant-shell-shadow-color: var(--md-sys-color-shadow);--praxis-ai-assistant-shell-highlight-color: var(--md-sys-color-on-surface);--praxis-ai-assistant-shell-tone-analytics: var(--md-sys-color-primary);--praxis-ai-assistant-shell-tone-resource: var(--md-sys-color-tertiary);--praxis-ai-assistant-shell-tone-success: var(--md-sys-color-tertiary);--praxis-ai-assistant-shell-tone-warning: var(--md-sys-color-secondary);--praxis-ai-assistant-shell-tone-danger: var(--md-sys-color-error);--praxis-ai-assistant-shell-tone-neutral: var(--md-sys-color-outline);position:fixed;box-sizing:border-box;min-width:0;min-height:0;display:flex;flex-direction:column;overflow:hidden;color:var(--md-sys-color-on-surface);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 70%,transparent);border-radius:8px;background:var(--md-sys-color-surface);box-shadow:0 24px 60px color-mix(in srgb,var(--praxis-ai-assistant-shell-shadow-color) 40%,transparent);pointer-events:auto;z-index:var(--praxis-ai-assistant-shell-z-index, 1200);container-type:inline-size}.praxis-ai-assistant-shell__header{flex:0 0 auto;display:flex;align-items:flex-start;gap:9px;padding:10px 10px 9px;border-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 72%,transparent);background:var(--md-sys-color-surface-container)}.praxis-ai-assistant-shell__header{justify-content:flex-start;border-bottom:1px solid;cursor:move;touch-action:none}.praxis-ai-assistant-shell__identity{flex:0 0 auto;display:grid;place-items:center;width:30px;height:30px;border-radius:8px;background:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary);box-shadow:0 6px 16px color-mix(in srgb,var(--md-sys-color-primary) 22%,transparent)}.praxis-ai-assistant-shell__identity mat-icon{width:18px;height:18px;font-size:18px}.praxis-ai-assistant-shell__title-group{min-width:0;flex:1 1 auto;display:grid;gap:4px}.praxis-ai-assistant-shell__title-row{min-width:0;display:flex;align-items:center;gap:8px}.praxis-ai-assistant-shell__badges{flex:0 0 auto;display:flex;align-items:center;justify-content:flex-end;gap:4px;min-width:0;flex-wrap:wrap}.praxis-ai-assistant-shell__badge{display:inline-flex;align-items:center;gap:5px;min-height:20px;max-width:120px;padding:2px 7px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 80%,transparent);border-radius:8px;color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container-high);font-size:11px;line-height:1.2;overflow-wrap:anywhere}.praxis-ai-assistant-shell__badge--context{color:var(--md-sys-color-on-surface);background:color-mix(in srgb,var(--md-sys-color-primary) 9%,var(--md-sys-color-surface-container-high))}.praxis-ai-assistant-shell__badge--state{border-color:transparent;background:transparent;color:var(--md-sys-color-on-surface-variant);padding-inline:3px}.praxis-ai-assistant-shell__badge--error{color:var(--md-sys-color-error);border-color:color-mix(in srgb,var(--md-sys-color-error) 60%,transparent)}.praxis-ai-assistant-shell__state-dot{flex:0 0 auto;width:6px;height:6px;border-radius:999px;background:var(--md-sys-color-primary);box-shadow:0 0 0 2px color-mix(in srgb,var(--md-sys-color-primary) 16%,transparent)}.praxis-ai-assistant-shell__badge--error .praxis-ai-assistant-shell__state-dot{background:var(--md-sys-color-error);box-shadow:0 0 0 2px color-mix(in srgb,var(--md-sys-color-error) 16%,transparent)}.praxis-ai-assistant-shell__title-group strong,.praxis-ai-assistant-shell__title-group p{min-width:0;margin:0;overflow-wrap:anywhere}.praxis-ai-assistant-shell__title-group strong{flex:1 1 auto;font-size:13px;line-height:1.2}.praxis-ai-assistant-shell__title-group p{color:var(--md-sys-color-on-surface-variant);font-size:11.5px;line-height:1.3}.praxis-ai-assistant-shell__header-actions{flex:0 0 auto;display:flex;align-items:center;gap:2px;margin-top:-3px}.praxis-ai-assistant-shell__header-actions .praxis-icon-button{color:var(--md-sys-color-on-surface-variant);opacity:.78}.praxis-ai-assistant-shell__header-actions .praxis-icon-button:hover,.praxis-ai-assistant-shell__header-actions .praxis-icon-button:focus-visible{opacity:1}.praxis-ai-assistant-shell__body{min-height:0;flex:1 1 auto;display:flex;flex-direction:column;gap:10px;padding:12px 12px 10px;overflow:auto;background:linear-gradient(180deg,var(--md-sys-color-surface-container-low),var(--md-sys-color-surface))}.praxis-ai-assistant-shell__context,.praxis-ai-assistant-shell__attachments{flex:0 0 auto;display:flex;align-items:center;gap:8px;overflow-x:auto;scrollbar-width:thin}.praxis-ai-assistant-shell__context-item{flex:0 0 auto;display:inline-flex;align-items:center;gap:5px;max-width:240px;padding:5px 8px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 70%,transparent);border-radius:8px;background:var(--md-sys-color-surface-container-high);font-size:12px;line-height:1.25}.praxis-ai-assistant-shell__context-item mat-icon{width:16px;height:16px;font-size:16px}.praxis-ai-assistant-shell__context-label,.praxis-ai-assistant-shell__context-value{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.praxis-ai-assistant-shell__context-label{color:var(--md-sys-color-on-surface)}.praxis-ai-assistant-shell__context-value{color:var(--md-sys-color-on-surface-variant)}.praxis-ai-assistant-shell__label{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.praxis-ai-assistant-shell__prompt{box-sizing:border-box;width:100%;min-height:48px;max-height:160px;resize:none;border:0;padding:12px 14px 4px;color:var(--md-sys-color-on-surface);background:transparent;font:inherit;line-height:1.45;outline:none;overflow-y:hidden;scrollbar-width:thin}.praxis-ai-assistant-shell__recommended{flex:0 0 auto;display:grid;gap:8px}.praxis-ai-assistant-shell__recommended-header{display:inline-flex;align-items:center;gap:6px;color:var(--md-sys-color-on-surface-variant);font-size:12px;font-weight:600;line-height:1.25}.praxis-ai-assistant-shell__recommended-header mat-icon{width:16px;height:16px;color:var(--md-sys-color-primary);font-size:16px;line-height:16px}.praxis-ai-assistant-shell__recommended-list{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,210px),1fr));gap:8px}.praxis-ai-assistant-shell__recommended-intent{--praxis-ai-assistant-shell-recommended-accent: var(--praxis-ai-assistant-shell-tone-neutral);appearance:none;border:1px solid color-mix(in srgb,var(--praxis-ai-assistant-shell-recommended-accent) 34%,transparent);border-radius:8px;background:linear-gradient(180deg,color-mix(in srgb,var(--praxis-ai-assistant-shell-recommended-accent) 8%,transparent),transparent),var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface);cursor:pointer;display:flex;gap:9px;min-width:0;min-height:86px;padding:10px;text-align:left;transition:border-color .16s ease,box-shadow .16s ease,background-color .16s ease}.praxis-ai-assistant-shell__recommended-intent:hover:not(:disabled),.praxis-ai-assistant-shell__recommended-intent:focus-visible{border-color:color-mix(in srgb,var(--praxis-ai-assistant-shell-recommended-accent) 68%,transparent);box-shadow:0 0 0 3px color-mix(in srgb,var(--praxis-ai-assistant-shell-recommended-accent) 15%,transparent);outline:none}.praxis-ai-assistant-shell__recommended-intent:disabled{cursor:default;opacity:.62}.praxis-ai-assistant-shell__recommended-icon{flex:0 0 auto;display:grid;place-items:center;width:30px;height:30px;border:1px solid color-mix(in srgb,var(--praxis-ai-assistant-shell-recommended-accent) 28%,transparent);border-radius:8px;background:color-mix(in srgb,var(--praxis-ai-assistant-shell-recommended-accent) 12%,transparent);color:var(--praxis-ai-assistant-shell-recommended-accent)}.praxis-ai-assistant-shell__recommended-icon mat-icon{width:18px;height:18px;font-size:18px;line-height:18px}.praxis-ai-assistant-shell__recommended-copy{min-width:0;display:grid;gap:5px}.praxis-ai-assistant-shell__recommended-title-row{min-width:0;display:flex;align-items:flex-start;justify-content:space-between;gap:8px}.praxis-ai-assistant-shell__recommended-title,.praxis-ai-assistant-shell__recommended-description,.praxis-ai-assistant-shell__recommended-group{min-width:0;overflow-wrap:anywhere}.praxis-ai-assistant-shell__recommended-title{color:var(--md-sys-color-on-surface);font-size:13px;font-weight:700;line-height:1.25}.praxis-ai-assistant-shell__recommended-group{flex:0 1 auto;max-width:44%;border-radius:8px;padding:2px 6px;background:color-mix(in srgb,var(--praxis-ai-assistant-shell-recommended-accent) 10%,transparent);color:color-mix(in srgb,var(--praxis-ai-assistant-shell-recommended-accent) 84%,var(--praxis-ai-assistant-shell-highlight-color));font-size:10.5px;font-weight:700;line-height:1.25}.praxis-ai-assistant-shell__recommended-description{color:var(--md-sys-color-on-surface-variant);font-size:12px;line-height:1.35}.praxis-ai-assistant-shell__recommended-cta{display:inline-flex;align-items:center;gap:5px;flex-wrap:wrap;color:color-mix(in srgb,var(--praxis-ai-assistant-shell-recommended-accent) 84%,var(--praxis-ai-assistant-shell-highlight-color));font-size:11.5px;font-weight:700;line-height:1.25}.praxis-ai-assistant-shell__recommended-cta mat-icon{width:15px;height:15px;font-size:15px;line-height:15px}.praxis-ai-assistant-shell__recommended-intent--tone-analytics{--praxis-ai-assistant-shell-recommended-accent: var(--praxis-ai-assistant-shell-tone-analytics)}.praxis-ai-assistant-shell__recommended-intent--tone-resource{--praxis-ai-assistant-shell-recommended-accent: var(--praxis-ai-assistant-shell-tone-resource)}.praxis-ai-assistant-shell__recommended-intent--tone-success{--praxis-ai-assistant-shell-recommended-accent: var(--praxis-ai-assistant-shell-tone-success)}.praxis-ai-assistant-shell__recommended-intent--tone-warning{--praxis-ai-assistant-shell-recommended-accent: var(--praxis-ai-assistant-shell-tone-warning)}.praxis-ai-assistant-shell__recommended-intent--tone-danger{--praxis-ai-assistant-shell-recommended-accent: var(--praxis-ai-assistant-shell-tone-danger)}.praxis-ai-assistant-shell__recommended-intent--tone-neutral{--praxis-ai-assistant-shell-recommended-accent: var(--praxis-ai-assistant-shell-tone-neutral)}.praxis-ai-assistant-shell__conversation{min-height:0;flex:1 1 auto;display:flex;flex-direction:column;gap:8px;overflow:auto;padding:2px}.praxis-ai-assistant-shell__message{max-width:86%;align-self:flex-start;padding:9px 11px;border-radius:8px;background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface);font-size:13px;line-height:1.35;overflow-wrap:anywhere}.praxis-ai-assistant-shell__message-content{white-space:normal}.praxis-ai-assistant-shell__message-content :where(p,ul,h3,h4,h5){margin:0}.praxis-ai-assistant-shell__message-content :where(p,ul,h3,h4,h5)+:where(p,ul,h3,h4,h5){margin-top:8px}.praxis-ai-assistant-shell__message-content ul,.praxis-ai-assistant-shell__message-content ol{margin:8px 0;padding-left:18px}.praxis-ai-assistant-shell__message-content li+li{margin-top:7px}.praxis-ai-assistant-shell__message-content code{padding:1px 4px;border-radius:4px;background:color-mix(in srgb,var(--md-sys-color-on-surface) 10%,transparent);font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:.94em}.praxis-ai-assistant-shell__assistant-content{display:grid;gap:8px}.praxis-ai-assistant-shell__assistant-block{display:grid;gap:8px;min-width:0}.praxis-ai-assistant-shell__assistant-block--summary,.praxis-ai-assistant-shell__assistant-block--recommendation{grid-template-columns:auto minmax(0,1fr);align-items:flex-start;padding:9px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 22%,transparent);border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-primary) 7%,transparent)}.praxis-ai-assistant-shell__assistant-block--recommendation{border-color:color-mix(in srgb,var(--praxis-ai-assistant-shell-tone-success) 26%,transparent);background:color-mix(in srgb,var(--praxis-ai-assistant-shell-tone-success) 8%,transparent)}.praxis-ai-assistant-shell__assistant-block-icon{display:grid;place-items:center;width:24px;height:24px;border-radius:8px;color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 14%,transparent)}.praxis-ai-assistant-shell__assistant-block--recommendation .praxis-ai-assistant-shell__assistant-block-icon{color:var(--praxis-ai-assistant-shell-tone-success);background:color-mix(in srgb,var(--praxis-ai-assistant-shell-tone-success) 14%,transparent)}.praxis-ai-assistant-shell__assistant-block-icon mat-icon{width:16px;height:16px;font-size:16px;line-height:16px}.praxis-ai-assistant-shell__assistant-block-copy{min-width:0}.praxis-ai-assistant-shell__assistant-block-copy strong{display:block;margin-bottom:3px}.praxis-ai-assistant-shell__assistant-block-heading{display:inline-flex;align-items:center;gap:6px;color:var(--md-sys-color-on-surface);font-size:12px;font-weight:700}.praxis-ai-assistant-shell__assistant-block-heading mat-icon{width:16px;height:16px;color:var(--md-sys-color-primary);font-size:16px}.praxis-ai-assistant-shell__assistant-resources{display:grid;gap:7px}.praxis-ai-assistant-shell__assistant-resource{display:grid;gap:7px;min-width:0;padding:9px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 76%,transparent);border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-surface-container-highest) 74%,transparent)}.praxis-ai-assistant-shell__assistant-resource-head{display:flex;align-items:flex-start;justify-content:space-between;gap:8px;min-width:0}.praxis-ai-assistant-shell__assistant-resource-head strong{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.praxis-ai-assistant-shell__assistant-resource-meta,.praxis-ai-assistant-shell__assistant-field-list,.praxis-ai-assistant-shell__assistant-evidence{display:flex;flex-wrap:wrap;gap:5px}.praxis-ai-assistant-shell__assistant-resource-meta span,.praxis-ai-assistant-shell__assistant-field,.praxis-ai-assistant-shell__assistant-evidence span{display:inline-flex;align-items:center;gap:4px;min-width:0;max-width:100%;padding:3px 6px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 62%,transparent);border-radius:999px;color:var(--md-sys-color-on-surface-variant);background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 82%,transparent);font-size:11px;line-height:1.25}.praxis-ai-assistant-shell__assistant-field{color:color-mix(in srgb,var(--md-sys-color-primary) 88%,var(--md-sys-color-on-surface));background:color-mix(in srgb,var(--md-sys-color-primary) 9%,transparent);border-color:color-mix(in srgb,var(--md-sys-color-primary) 22%,transparent)}.praxis-ai-assistant-shell__assistant-evidence span{color:color-mix(in srgb,var(--praxis-ai-assistant-shell-tone-success) 85%,var(--md-sys-color-on-surface));background:color-mix(in srgb,var(--praxis-ai-assistant-shell-tone-success) 9%,transparent);border-color:color-mix(in srgb,var(--praxis-ai-assistant-shell-tone-success) 22%,transparent)}.praxis-ai-assistant-shell__assistant-evidence mat-icon{width:13px;height:13px;font-size:13px}.praxis-ai-assistant-shell__assistant-resource p{margin:0;color:var(--md-sys-color-on-surface-variant)}.praxis-ai-assistant-shell__message-actions{display:flex;align-items:center;gap:4px;flex-wrap:wrap;margin-top:8px}.praxis-ai-assistant-shell__message-action:not(.praxis-icon-button){min-height:28px;padding:0 8px;border-radius:8px;font-size:12px}.praxis-ai-assistant-shell__message-action--icon{color:var(--md-sys-color-on-surface-variant)}.praxis-ai-assistant-shell__message-feedback,.praxis-ai-assistant-shell__message-feedback-submitted{display:flex;align-items:center;gap:4px;margin-top:8px}.praxis-ai-assistant-shell__message-feedback-action{color:var(--md-sys-color-on-surface-variant)}.praxis-ai-assistant-shell__message-feedback-submitted mat-icon{display:block;width:17px;height:17px;font-size:17px;line-height:17px}.praxis-ai-assistant-shell__message-feedback-submitted{color:var(--md-sys-color-on-surface-variant);font-size:12px}.praxis-ai-assistant-shell__message--assistant{border-bottom-left-radius:2px}.praxis-ai-assistant-shell__message--user{align-self:flex-end;border-bottom-right-radius:2px;background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}.praxis-ai-assistant-shell__message--status{color:var(--md-sys-color-on-surface-variant)}.praxis-ai-assistant-shell__message--error,.praxis-ai-assistant-shell__error{color:var(--md-sys-color-error)}.praxis-ai-assistant-shell__quick-replies{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,520px),1fr));gap:8px;align-items:stretch;padding-bottom:4px}.praxis-ai-assistant-shell__quick-replies--inline{display:flex;flex-wrap:wrap;align-items:center;gap:6px}.praxis-ai-assistant-shell__attachment{flex:0 0 auto;display:inline-flex;align-items:center;gap:7px;max-width:260px;min-height:34px;padding:4px 4px 4px 8px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 70%,transparent);border-radius:8px;background:var(--md-sys-color-surface-container-high)}.praxis-ai-assistant-shell__attachment--error{border-color:color-mix(in srgb,var(--md-sys-color-error) 60%,transparent)}.praxis-ai-assistant-shell__attachment-preview{flex:0 0 auto;width:28px;height:28px;border-radius:6px;object-fit:cover}.praxis-ai-assistant-shell__attachment-name,.praxis-ai-assistant-shell__attachment-kind{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:12px}.praxis-ai-assistant-shell__attachment-name{color:var(--md-sys-color-on-surface)}.praxis-ai-assistant-shell__attachment-kind{color:var(--md-sys-color-on-surface-variant)}.praxis-ai-assistant-shell__quick-reply{--praxis-ai-assistant-shell-quick-reply-accent: var(--md-sys-color-primary);--praxis-ai-assistant-shell-quick-reply-background: color-mix( in srgb, var(--praxis-ai-assistant-shell-quick-reply-accent) 7%, var(--md-sys-color-surface-container-high) );--praxis-ai-assistant-shell-quick-reply-foreground: var(--md-sys-color-on-surface);width:100%;max-width:100%;height:auto;min-height:0;position:relative;overflow:hidden;padding:15px 16px;align-items:stretch;border-color:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 36%,transparent);border-radius:22px;color:var(--praxis-ai-assistant-shell-quick-reply-foreground);background:linear-gradient(135deg,color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 16%,transparent),transparent 46%),radial-gradient(circle at 92% 10%,color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 22%,transparent),transparent 32%),var(--praxis-ai-assistant-shell-quick-reply-background);box-shadow:0 18px 42px color-mix(in srgb,var(--praxis-ai-assistant-shell-shadow-color) 22%,transparent),inset 0 1px color-mix(in srgb,var(--praxis-ai-assistant-shell-highlight-color) 16%,transparent);letter-spacing:normal;white-space:normal;text-align:left;text-transform:none;-webkit-user-select:none;user-select:none;transition:border-color .16s ease,box-shadow .16s ease,transform .16s ease,background .16s ease;--mdc-outlined-button-container-height: auto;--mat-outlined-button-horizontal-padding: 0}.praxis-ai-assistant-shell__quick-reply:hover:not(:disabled),.praxis-ai-assistant-shell__quick-reply:focus-visible{border-color:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 74%,transparent);box-shadow:0 18px 42px color-mix(in srgb,var(--praxis-ai-assistant-shell-shadow-color) 24%,transparent),0 0 0 3px color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 18%,transparent),inset 0 1px color-mix(in srgb,var(--praxis-ai-assistant-shell-highlight-color) 18%,transparent);transform:translateY(-1px)}.praxis-ai-assistant-shell__quick-reply--contextual-action{padding:10px 12px;border-color:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 34%,transparent);border-radius:8px;background:linear-gradient(90deg,color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 15%,transparent),color-mix(in srgb,var(--md-sys-color-surface-container-high) 92%,transparent)),var(--md-sys-color-surface-container-high);box-shadow:none}.praxis-ai-assistant-shell__quick-reply--guided-action{padding:10px 12px;border-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 82%,transparent);border-radius:8px;background:var(--md-sys-color-surface-container-high);box-shadow:none}.praxis-ai-assistant-shell__quick-reply--conversation-action{width:auto;min-width:0;padding:7px 11px;border-radius:999px;background:color-mix(in srgb,var(--md-sys-color-primary-container) 22%,var(--md-sys-color-surface-container-high));box-shadow:none}.praxis-ai-assistant-shell__quick-reply--conversation-action ::ng-deep .mdc-button__label{display:inline-flex;grid-template-columns:none;align-items:center;gap:7px}.praxis-ai-assistant-shell__quick-reply--conversation-action .praxis-ai-assistant-shell__quick-reply-icon-frame{width:22px;height:22px;border:0;background:transparent;box-shadow:none}.praxis-ai-assistant-shell__quick-reply--conversation-action .praxis-ai-assistant-shell__quick-reply-icon{width:17px;height:17px;font-size:17px}.praxis-ai-assistant-shell__quick-reply--conversation-action .praxis-ai-assistant-shell__quick-reply-copy,.praxis-ai-assistant-shell__quick-reply--conversation-action .praxis-ai-assistant-shell__quick-reply-heading{display:inline-flex;gap:0}.praxis-ai-assistant-shell__quick-reply--conversation-action .praxis-ai-assistant-shell__quick-reply-label{font-size:12.5px;font-weight:680;white-space:nowrap}.praxis-ai-assistant-shell__quick-reply--source-review{padding:11px 12px;border-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 88%,transparent);border-radius:8px;background:linear-gradient(90deg,color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 7%,transparent),transparent 58%),var(--md-sys-color-surface-container-high);box-shadow:none}.praxis-ai-assistant-shell__quick-reply--contextual-action:hover:not(:disabled),.praxis-ai-assistant-shell__quick-reply--contextual-action:focus-visible{border-color:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 62%,transparent);box-shadow:0 0 0 2px color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 15%,transparent);transform:none}.praxis-ai-assistant-shell__quick-reply--guided-action:hover:not(:disabled),.praxis-ai-assistant-shell__quick-reply--guided-action:focus-visible,.praxis-ai-assistant-shell__quick-reply--source-review:hover:not(:disabled),.praxis-ai-assistant-shell__quick-reply--source-review:focus-visible{border-color:color-mix(in srgb,var(--md-sys-color-primary) 64%,var(--md-sys-color-outline-variant));background:color-mix(in srgb,var(--md-sys-color-primary-container) 18%,var(--md-sys-color-surface-container-high));box-shadow:0 0 0 2px color-mix(in srgb,var(--md-sys-color-primary) 14%,transparent);transform:none}.praxis-ai-assistant-shell__quick-reply--contextual-action .praxis-ai-assistant-shell__quick-reply-ambient,.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-ambient,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-ambient{display:none}.praxis-ai-assistant-shell__quick-reply--contextual-action ::ng-deep .mdc-button__label,.praxis-ai-assistant-shell__quick-reply--guided-action ::ng-deep .mdc-button__label,.praxis-ai-assistant-shell__quick-reply--source-review ::ng-deep .mdc-button__label{gap:10px;align-items:flex-start}.praxis-ai-assistant-shell__quick-reply--contextual-action .praxis-ai-assistant-shell__quick-reply-icon-frame,.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-icon-frame,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-icon-frame{width:34px;height:34px;border-radius:8px;box-shadow:none}.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-icon-frame,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-icon-frame{border-color:color-mix(in srgb,var(--md-sys-color-primary) 24%,var(--md-sys-color-outline-variant));color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary-container) 34%,var(--md-sys-color-surface-container-high))}.praxis-ai-assistant-shell__quick-reply--contextual-action .praxis-ai-assistant-shell__quick-reply-icon,.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-icon,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-icon{width:19px;height:19px;font-size:19px}.praxis-ai-assistant-shell__quick-reply--contextual-action .praxis-ai-assistant-shell__quick-reply-copy,.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-copy,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-copy{gap:6px}.praxis-ai-assistant-shell__quick-reply--contextual-action .praxis-ai-assistant-shell__quick-reply-label,.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-label,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-label{font-size:13.5px;font-weight:760;letter-spacing:0}.praxis-ai-assistant-shell__quick-reply--contextual-action .praxis-ai-assistant-shell__quick-reply-description,.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-description,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-description{display:-webkit-box;overflow:hidden;font-size:12px;line-height:1.34;-webkit-box-orient:vertical;-webkit-line-clamp:2}.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-description{color:var(--md-sys-color-on-surface-variant)}.praxis-ai-assistant-shell__quick-reply--contextual-action .praxis-ai-assistant-shell__quick-reply-badge,.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-badge,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-badge{border-radius:8px;font-size:10px;letter-spacing:0}.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-badge,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-badge{border-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 76%,transparent);color:var(--md-sys-color-on-surface-variant);background:color-mix(in srgb,var(--md-sys-color-surface-container-lowest) 62%,transparent)}.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-cta,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-cta{color:var(--md-sys-color-primary)}.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-context{gap:5px}.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-context-chip{border-radius:8px;padding:4px 7px;background:color-mix(in srgb,var(--md-sys-color-surface-container-lowest) 66%,transparent);font-size:10.5px;font-weight:650}.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-actions{max-width:40%}.praxis-ai-assistant-shell__quick-reply--contextual-action .praxis-ai-assistant-shell__quick-reply-context-chip{border-radius:8px;padding:4px 7px;font-size:10.5px;font-weight:650}.praxis-ai-assistant-shell__quick-reply--contextual-action .praxis-ai-assistant-shell__quick-reply-cta,.praxis-ai-assistant-shell__quick-reply--guided-action .praxis-ai-assistant-shell__quick-reply-cta,.praxis-ai-assistant-shell__quick-reply--source-review .praxis-ai-assistant-shell__quick-reply-cta{font-size:11.5px}.praxis-ai-assistant-shell__quick-reply--compact{justify-self:start;width:fit-content;min-width:min(100%,210px);max-width:min(100%,320px);padding:9px 11px;border-radius:16px;background:linear-gradient(135deg,color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 10%,transparent),transparent 55%),var(--md-sys-color-surface-container-high);box-shadow:0 8px 18px color-mix(in srgb,var(--praxis-ai-assistant-shell-shadow-color) 16%,transparent),inset 0 1px color-mix(in srgb,var(--praxis-ai-assistant-shell-highlight-color) 10%,transparent)}.praxis-ai-assistant-shell__quick-reply.praxis-ai-assistant-shell__quick-reply--compact ::ng-deep .mdc-button__label{align-items:center;gap:10px}.praxis-ai-assistant-shell__quick-reply--compact .praxis-ai-assistant-shell__quick-reply-icon-frame{width:34px;height:34px;border-radius:12px}.praxis-ai-assistant-shell__quick-reply--compact .praxis-ai-assistant-shell__quick-reply-icon{width:19px;height:19px;font-size:19px}.praxis-ai-assistant-shell__quick-reply--compact .praxis-ai-assistant-shell__quick-reply-copy{gap:4px}.praxis-ai-assistant-shell__quick-reply--compact .praxis-ai-assistant-shell__quick-reply-header{align-items:center}.praxis-ai-assistant-shell__quick-reply--compact .praxis-ai-assistant-shell__quick-reply-label{font-size:13px;line-height:1.2}.praxis-ai-assistant-shell__quick-reply--compact .praxis-ai-assistant-shell__quick-reply-badge,.praxis-ai-assistant-shell__quick-reply--compact .praxis-ai-assistant-shell__quick-reply-cta{display:none}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply{width:auto;min-width:0;max-width:100%;padding:6px 10px;border-radius:999px;box-shadow:none}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply--guided-action{border-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 76%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container-high) 96%,transparent)}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply--guided-action:hover:not(:disabled),.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply--guided-action:focus-visible{border-color:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 52%,transparent);background:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 9%,var(--md-sys-color-surface-container-high));box-shadow:0 0 0 2px color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 12%,transparent)}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply ::ng-deep .mdc-button__label{display:inline-flex;grid-template-columns:none;align-items:center;gap:6px;width:auto}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply ::ng-deep .mat-mdc-button-touch-target{min-height:34px}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-icon-frame{width:18px;height:18px;border:0;border-radius:0;background:transparent;box-shadow:none}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-icon{width:16px;height:16px;color:var(--praxis-ai-assistant-shell-quick-reply-accent);font-size:16px}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-copy,.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-heading,.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-header{display:inline-flex;align-items:center;gap:0}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-label{color:var(--md-sys-color-on-surface);font-size:12.5px;font-weight:650;line-height:1.2;white-space:nowrap}.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-description,.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-actions,.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-badge,.praxis-ai-assistant-shell__quick-replies--inline .praxis-ai-assistant-shell__quick-reply-cta{display:none}.praxis-ai-assistant-shell__quick-reply ::ng-deep .mdc-button__label{position:relative;z-index:1;min-width:0;display:grid;grid-template-columns:auto minmax(0,1fr);align-items:flex-start;gap:14px;width:100%;height:auto;line-height:normal}.praxis-ai-assistant-shell__quick-reply-ambient{position:absolute;inset:0;pointer-events:none}.praxis-ai-assistant-shell__quick-reply-ambient:before{content:\"\";position:absolute;inset:0 18px auto;height:1px;border-radius:999px;background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 90%,var(--praxis-ai-assistant-shell-highlight-color)),transparent);opacity:.58}.praxis-ai-assistant-shell__quick-reply-ambient:after{content:\"\";position:absolute;top:-34px;right:-44px;width:150px;height:150px;border-radius:999px;background:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 13%,transparent);filter:blur(18px)}.praxis-ai-assistant-shell__quick-reply ::ng-deep .mat-mdc-button-touch-target{height:100%;min-height:48px}.praxis-ai-assistant-shell__quick-reply-icon-frame{flex:0 0 auto;width:46px;height:46px;display:inline-grid;place-items:center;border:1px solid color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 34%,transparent);border-radius:17px;color:var(--praxis-ai-assistant-shell-quick-reply-accent);background:linear-gradient(145deg,color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 24%,transparent),color-mix(in srgb,var(--praxis-ai-assistant-shell-highlight-color) 6%,transparent));box-shadow:inset 0 1px color-mix(in srgb,var(--praxis-ai-assistant-shell-highlight-color) 18%,transparent),0 10px 24px color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 12%,transparent)}.praxis-ai-assistant-shell__quick-reply-icon{width:24px;height:24px;font-size:24px}.praxis-ai-assistant-shell__quick-reply-details{flex:0 0 auto;width:24px;height:24px;display:inline-grid;place-items:center;border:1px solid color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 14%,transparent);border-radius:50%;color:var(--md-sys-color-on-surface-variant);background:color-mix(in srgb,var(--md-sys-color-outline) 14%,transparent);font-size:17px;opacity:.9}.praxis-ai-assistant-shell__quick-reply-copy{min-width:0;display:grid;gap:10px;flex:1 1 auto}.praxis-ai-assistant-shell__quick-reply-header{min-width:0;display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.praxis-ai-assistant-shell__quick-reply-heading{min-width:0;display:grid;gap:5px}.praxis-ai-assistant-shell__quick-reply-actions{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:flex-end;gap:7px;max-width:46%}.praxis-ai-assistant-shell__quick-reply-label,.praxis-ai-assistant-shell__quick-reply-description{min-width:0;overflow-wrap:anywhere}.praxis-ai-assistant-shell__quick-reply-label{color:var(--md-sys-color-on-surface);font-size:17px;font-weight:760;letter-spacing:.005em;line-height:1.18;text-transform:none}.praxis-ai-assistant-shell__quick-reply-badge{flex:0 0 auto;max-width:100%;padding:4px 8px;border:1px solid color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 28%,transparent);border-radius:999px;color:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 86%,var(--praxis-ai-assistant-shell-highlight-color));background:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 11%,transparent);font-size:10.5px;font-weight:700;letter-spacing:.02em;line-height:1.1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.praxis-ai-assistant-shell__quick-reply-description{color:color-mix(in srgb,var(--md-sys-color-on-surface) 80%,transparent);font-size:13px;line-height:1.46}.praxis-ai-assistant-shell__quick-reply-context{display:flex;flex-wrap:wrap;gap:7px;align-items:center}.praxis-ai-assistant-shell__quick-reply-context-chip{min-width:0;display:inline-flex;align-items:center;gap:4px;max-width:100%;padding:5px 8px;border:1px solid color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 22%,transparent);border-radius:999px;color:color-mix(in srgb,var(--md-sys-color-on-surface) 82%,transparent);background:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 9%,transparent);font-size:11px;font-weight:650;line-height:1.15}.praxis-ai-assistant-shell__quick-reply-context-chip mat-icon{width:14px;height:14px;color:var(--praxis-ai-assistant-shell-quick-reply-accent);font-size:14px}.praxis-ai-assistant-shell__quick-reply-context-chip span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.praxis-ai-assistant-shell__quick-reply-insights{display:grid;grid-template-columns:repeat(auto-fit,minmax(145px,1fr));gap:8px;padding:8px;border:1px solid color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 16%,transparent);border-radius:16px;background:linear-gradient(180deg,color-mix(in srgb,var(--praxis-ai-assistant-shell-highlight-color) 5%,transparent),color-mix(in srgb,var(--md-sys-color-surface-container-lowest) 26%,transparent))}.praxis-ai-assistant-shell__quick-reply-insight{min-width:0;display:grid;grid-template-columns:20px minmax(0,1fr);gap:8px;align-items:start;padding:8px;border:1px solid color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 10%,transparent);border-radius:13px;color:color-mix(in srgb,var(--md-sys-color-on-surface) 86%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container-high) 44%,transparent);font-size:12px;line-height:1.35}.praxis-ai-assistant-shell__quick-reply-insight mat-icon{width:17px;height:17px;color:var(--praxis-ai-assistant-shell-quick-reply-accent);font-size:17px;opacity:.9}.praxis-ai-assistant-shell__quick-reply-insight-copy{min-width:0;display:grid;gap:1px}.praxis-ai-assistant-shell__quick-reply-insight-label{color:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 82%,var(--praxis-ai-assistant-shell-highlight-color));font-size:10.5px;font-weight:760;letter-spacing:.045em;line-height:1.2;text-transform:uppercase}.praxis-ai-assistant-shell__quick-reply-insight-value{min-width:0;overflow-wrap:anywhere}.praxis-ai-assistant-shell__quick-reply-cta{display:inline-flex;align-items:center;justify-self:start;gap:5px;padding:3px 0;color:color-mix(in srgb,var(--praxis-ai-assistant-shell-quick-reply-accent) 84%,var(--praxis-ai-assistant-shell-highlight-color));font-size:12px;font-weight:760;letter-spacing:.01em;line-height:1.2}.praxis-ai-assistant-shell__quick-reply-cta mat-icon{width:15px;height:15px;font-size:15px;transition:transform .16s ease}.praxis-ai-assistant-shell__quick-reply:hover:not(:disabled) .praxis-ai-assistant-shell__quick-reply-cta mat-icon,.praxis-ai-assistant-shell__quick-reply:focus-visible .praxis-ai-assistant-shell__quick-reply-cta mat-icon{transform:translate(2px)}.praxis-ai-assistant-shell__quick-reply--tone-analytics{--praxis-ai-assistant-shell-quick-reply-accent: var(--praxis-ai-assistant-shell-tone-analytics)}.praxis-ai-assistant-shell__quick-reply--tone-resource{--praxis-ai-assistant-shell-quick-reply-accent: var(--praxis-ai-assistant-shell-tone-resource)}.praxis-ai-assistant-shell__quick-reply--tone-warning{--praxis-ai-assistant-shell-quick-reply-accent: var(--praxis-ai-assistant-shell-tone-warning)}.praxis-ai-assistant-shell__quick-reply--tone-success{--praxis-ai-assistant-shell-quick-reply-accent: var(--praxis-ai-assistant-shell-tone-success)}.praxis-ai-assistant-shell__quick-reply--tone-danger{--praxis-ai-assistant-shell-quick-reply-accent: var(--praxis-ai-assistant-shell-tone-danger)}.praxis-ai-assistant-shell__quick-reply--tone-neutral{--praxis-ai-assistant-shell-quick-reply-accent: var(--praxis-ai-assistant-shell-tone-neutral)}@media(max-width:640px){.praxis-ai-assistant-shell__context{flex-wrap:wrap;overflow-x:visible}.praxis-ai-assistant-shell__context-item{max-width:min(100%,240px)}.praxis-ai-assistant-shell__quick-reply{padding:13px;border-radius:19px}.praxis-ai-assistant-shell__quick-reply ::ng-deep .mdc-button__label{grid-template-columns:minmax(0,1fr);gap:10px}.praxis-ai-assistant-shell__quick-reply-icon-frame{width:38px;height:38px;border-radius:14px}.praxis-ai-assistant-shell__quick-reply-header{display:grid}.praxis-ai-assistant-shell__quick-reply-actions{justify-content:flex-start;max-width:100%}.praxis-ai-assistant-shell__quick-reply-insights{grid-template-columns:minmax(0,1fr)}}@container (max-width: 400px){.praxis-ai-assistant-shell__header{display:grid;grid-template-columns:auto minmax(0,1fr) auto}.praxis-ai-assistant-shell__title-row{display:grid;gap:5px}.praxis-ai-assistant-shell__badges{justify-content:flex-start}.praxis-ai-assistant-shell__badge{max-width:100%}.praxis-ai-assistant-shell__context{flex-wrap:wrap;overflow-x:visible}.praxis-ai-assistant-shell__context-item{flex:1 1 150px;max-width:100%}.praxis-ai-assistant-shell__context-label,.praxis-ai-assistant-shell__context-value{overflow:visible;text-overflow:clip;white-space:normal;overflow-wrap:anywhere}.praxis-ai-assistant-shell__recommended-title-row,.praxis-ai-assistant-shell__assistant-resource-head{display:grid;justify-content:stretch}.praxis-ai-assistant-shell__recommended-group{max-width:100%;width:fit-content}.praxis-ai-assistant-shell__assistant-resource-head strong{overflow:visible;text-overflow:clip;white-space:normal;overflow-wrap:anywhere}}.praxis-ai-assistant-shell__status,.praxis-ai-assistant-shell__error{margin:0;font-size:13px;line-height:1.35;overflow-wrap:anywhere}.praxis-ai-assistant-shell__footer{flex:0 0 auto;padding:8px 10px 10px;border-top:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 72%,transparent);background:var(--md-sys-color-surface-container-low)}.praxis-ai-assistant-shell__composer{display:grid;gap:4px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container-lowest);box-shadow:inset 0 1px color-mix(in srgb,var(--praxis-ai-assistant-shell-highlight-color) 4%,transparent)}.praxis-ai-assistant-shell__composer:focus-within{border-color:var(--md-sys-color-primary);box-shadow:0 0 0 2px color-mix(in srgb,var(--md-sys-color-primary) 16%,transparent)}.praxis-ai-assistant-shell__composer-actions{display:flex;align-items:center;justify-content:flex-end;gap:4px;min-height:44px;padding:0 7px 6px;flex-wrap:nowrap}.praxis-ai-assistant-shell__voice-action{margin-right:auto;color:var(--md-sys-color-on-surface-variant)}.praxis-ai-assistant-shell__voice-action--active{color:var(--md-sys-color-error)}.praxis-ai-assistant-shell__voice-action--error{color:var(--praxis-ai-assistant-shell-tone-warning)}.praxis-ai-assistant-shell__icon-action--tone-governance,.praxis-ai-assistant-shell__icon-action--tone-primary{--praxis-icon-button-filled-background: var(--md-sys-color-primary);--praxis-icon-button-filled-foreground: var(--md-sys-color-on-primary)}.praxis-ai-assistant-shell__icon-action--tone-success{--praxis-icon-button-filled-background: var(--praxis-ai-assistant-shell-tone-success);--praxis-icon-button-filled-foreground: var(--md-sys-color-on-tertiary)}.praxis-ai-assistant-shell__icon-action--tone-warning{--praxis-icon-button-filled-background: var(--praxis-ai-assistant-shell-tone-warning);--praxis-icon-button-filled-foreground: var(--md-sys-color-on-secondary)}.praxis-ai-assistant-shell__icon-action--tone-danger{--praxis-icon-button-filled-background: var(--md-sys-color-error);--praxis-icon-button-filled-foreground: var(--md-sys-color-on-error)}.praxis-ai-assistant-shell__icon-action--tone-neutral,.praxis-ai-assistant-shell__icon-action--tone-secondary{--praxis-icon-button-filled-background: var(--md-sys-color-surface-variant);--praxis-icon-button-filled-foreground: var(--md-sys-color-on-surface-variant)}.praxis-ai-assistant-shell__voice-status{margin:-2px 10px 8px;color:var(--md-sys-color-on-surface-variant);font-size:12px;line-height:1.3}.praxis-ai-assistant-shell__action{min-height:36px;border-radius:10px;font-weight:650}.praxis-ai-assistant-shell__action mat-icon{width:18px;height:18px;margin-right:6px;font-size:18px}.praxis-ai-assistant-shell__action--secondary{color:var(--md-sys-color-on-surface-variant)}.praxis-ai-assistant-shell__action--tone-governance{color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 10%,transparent)}.praxis-ai-assistant-shell__action--tone-success{color:var(--praxis-ai-assistant-shell-tone-success);background:color-mix(in srgb,var(--praxis-ai-assistant-shell-tone-success) 10%,transparent)}.praxis-ai-assistant-shell__action--tone-warning{color:var(--praxis-ai-assistant-shell-tone-warning);background:color-mix(in srgb,var(--praxis-ai-assistant-shell-tone-warning) 10%,transparent)}.praxis-ai-assistant-shell__action--tone-danger{color:var(--md-sys-color-error);background:color-mix(in srgb,var(--md-sys-color-error) 10%,transparent)}.praxis-ai-assistant-shell__resize-handle{position:absolute;z-index:2;border:0;background:transparent;touch-action:none}.praxis-ai-assistant-shell__resize-handle--n,.praxis-ai-assistant-shell__resize-handle--s{left:16px;right:16px;height:10px;cursor:ns-resize}.praxis-ai-assistant-shell__resize-handle--n{top:-5px}.praxis-ai-assistant-shell__resize-handle--s{bottom:-5px}.praxis-ai-assistant-shell__resize-handle--e,.praxis-ai-assistant-shell__resize-handle--w{top:16px;bottom:16px;width:10px;cursor:ew-resize}.praxis-ai-assistant-shell__resize-handle--e{right:-5px}.praxis-ai-assistant-shell__resize-handle--w{left:-5px}.praxis-ai-assistant-shell__resize-handle--ne,.praxis-ai-assistant-shell__resize-handle--nw,.praxis-ai-assistant-shell__resize-handle--se,.praxis-ai-assistant-shell__resize-handle--sw{width:22px;height:22px}.praxis-ai-assistant-shell__resize-handle--ne{top:-5px;right:-5px;cursor:nesw-resize}.praxis-ai-assistant-shell__resize-handle--nw{top:-5px;left:-5px;cursor:nwse-resize}.praxis-ai-assistant-shell__resize-handle--se{right:-5px;bottom:-5px;cursor:nwse-resize}.praxis-ai-assistant-shell__resize-handle--sw{bottom:-5px;left:-5px;cursor:nesw-resize}.praxis-ai-assistant-shell__resize-handle--se:after{content:\"\";position:absolute;right:8px;bottom:8px;width:10px;height:10px;border-right:2px solid var(--md-sys-color-outline);border-bottom:2px solid var(--md-sys-color-outline)}\n"] }]
|
|
9668
9832
|
}], propDecorators: { labels: [{
|
|
9669
9833
|
type: Input
|
|
9670
9834
|
}], mode: [{
|
|
@@ -10520,9 +10684,14 @@ class AiRuleWizardDialogComponent {
|
|
|
10520
10684
|
<mat-icon>lightbulb</mat-icon>
|
|
10521
10685
|
Sugestões da IA
|
|
10522
10686
|
</div>
|
|
10523
|
-
<button
|
|
10524
|
-
|
|
10525
|
-
|
|
10687
|
+
<button
|
|
10688
|
+
praxisIconButton="refresh"
|
|
10689
|
+
size="dense"
|
|
10690
|
+
type="button"
|
|
10691
|
+
aria-label="Atualizar sugestões da IA"
|
|
10692
|
+
(click)="reloadSuggestions()"
|
|
10693
|
+
[disabled]="loadingSuggestions"
|
|
10694
|
+
></button>
|
|
10526
10695
|
</div>
|
|
10527
10696
|
@if (!loadingSuggestions && suggestions.length > 0) {
|
|
10528
10697
|
<div class="suggestions-body">
|
|
@@ -10694,7 +10863,7 @@ class AiRuleWizardDialogComponent {
|
|
|
10694
10863
|
}
|
|
10695
10864
|
</mat-dialog-actions>
|
|
10696
10865
|
</div>
|
|
10697
|
-
`, isInline: true, styles: [".ai-wizard-container{position:relative;padding-bottom:0;max-height:85vh;display:flex;flex-direction:column}.wizard-title{display:flex;align-items:center;gap:12px;color:#673ab7;margin:0;padding:20px 24px;border-bottom:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface);z-index:1}.step-badge{font-size:12px;background:#673ab71a;padding:2px 8px;border-radius:12px;margin-left:auto}.ai-icon{color:#673ab7}.wizard-content{flex:1;overflow-y:auto;padding:0;min-height:300px}.step-prompt,.step-review{padding:20px 24px}.intro-text{color:var(--md-sys-color-on-surface-variant);margin-bottom:24px;font-size:14px}.form-row{display:flex;gap:16px;margin-bottom:8px}.type-select{width:200px}.prompt-input{width:100%}.properties-panel{margin-top:16px;box-shadow:none;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px!important}.suggestions-card{border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;padding:12px;margin:12px 0 4px;background:var(--md-sys-color-surface-container-low)}.suggestions-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px;gap:8px}.suggestions-header .title{display:flex;align-items:center;gap:8px;font-weight:600;font-size:14px}.suggestions-body{display:flex;flex-wrap:wrap;gap:8px}.suggestion-chip{cursor:pointer;max-width:100%;white-space:normal;line-height:1.3}.suggestions-loading,.suggestions-empty{display:flex;align-items:center;gap:8px;color:var(--md-sys-color-on-surface-variant);font-size:13px}.properties-list{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:8px;padding:8px 0}.prop-item{font-size:12px;display:flex;align-items:center;gap:6px}.prop-name{font-weight:600;font-family:monospace}.prop-type{color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container);padding:2px 6px;border-radius:4px;font-size:10px}.prop-desc{color:var(--md-sys-color-on-surface-variant);font-style:italic}.review-header{margin-bottom:20px;border-bottom:1px solid var(--md-sys-color-outline-variant);padding-bottom:12px}.review-header h3{margin:0 0 8px;font-size:18px}.target-badges{display:flex;gap:8px}.badge-type{background:#e0e0e0;color:#424242;padding:2px 8px;border-radius:4px;font-size:11px;text-transform:uppercase;font-weight:700}.badge-id{background:var(--md-sys-color-secondary-container);color:var(--md-sys-color-on-secondary-container);padding:2px 8px;border-radius:4px;font-size:12px;font-family:monospace}.warnings-box{background:#fff8e1;border:1px solid #ffecb3;border-radius:8px;padding:12px;margin-bottom:16px}.warning-title{display:flex;align-items:center;gap:8px;color:#f57f17;font-weight:600;font-size:13px;margin-bottom:8px}.warning-title mat-icon{font-size:18px;width:18px;height:18px}.warning-list{margin:0;padding-left:24px;font-size:13px;color:#5d4037}.summary-view{padding:16px;background:var(--md-sys-color-surface-container-low);border-radius:8px;margin-top:12px}.summary-row{margin-bottom:12px}.summary-row:last-child{margin-bottom:0}.label{display:block;font-size:11px;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant);margin-bottom:4px}.value{font-size:14px}.value.condition{font-family:monospace;color:var(--md-sys-color-primary);background:#00000008;padding:2px 4px;border-radius:4px}.props-grid{display:flex;flex-wrap:wrap;gap:12px}.prop-pair{background:#fff;border:1px solid var(--md-sys-color-outline-variant);padding:4px 8px;border-radius:4px;font-size:13px}.p-key{font-weight:600;margin-right:4px}.p-val{color:var(--md-sys-color-primary)}.json-preview{background:#f5f5f5;padding:12px;border-radius:8px;font-size:12px;max-height:300px;overflow:auto;margin-top:12px}.error-box{margin-top:16px;padding:12px;background-color:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container);border-radius:8px;display:flex;align-items:flex-start;gap:12px;font-size:13px}.ai-processing-overlay{position:absolute;inset:0;background:#ffffffd9;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:10;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:24px;border-radius:8px}.sparkle-icon{font-size:48px;width:48px;height:48px;color:#673ab7;animation:ai-pulse 2s infinite;z-index:2}.ai-pulse-ring{position:absolute;width:80px;height:80px;border-radius:50%;background:radial-gradient(circle,#673ab733,#673ab700 70%);animation:ai-ripple 2s infinite;z-index:1}.processing-text{text-align:center;z-index:2}.processing-text h3{margin:0 0 8px;color:#311b92;font-size:18px;font-weight:500}.fade-text{margin:0;color:#673ab7;font-size:14px;font-style:italic;min-height:20px;animation:text-fade .5s ease-in-out}@keyframes ai-pulse{0%{transform:scale(1);opacity:1;text-shadow:0 0 10px rgba(103,58,183,.5)}50%{transform:scale(1.1);opacity:.8;text-shadow:0 0 20px rgba(103,58,183,.8)}to{transform:scale(1);opacity:1;text-shadow:0 0 10px rgba(103,58,183,.5)}}@keyframes ai-ripple{0%{transform:scale(.8);opacity:.6}to{transform:scale(2.5);opacity:0}}@keyframes text-fade{0%{opacity:0;transform:translateY(5px)}to{opacity:1;transform:translateY(0)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.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: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1$1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1$1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1$1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1$1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i9.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i9.MatLabel, selector: "mat-label" }, { kind: "directive", type: i9.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i10$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i11.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i11.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i7.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "ngmodule", type: MatSnackBarModule }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i13.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i13.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i13.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i14.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i14.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i15.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["role", "id", "aria-label", "aria-description", "value", "color", "removable", "highlighted", "disableRipple", "disabled"], outputs: ["removed", "destroyed"], exportAs: ["matChip"] }, { kind: "component", type: i15.MatChipSet, selector: "mat-chip-set", inputs: ["disabled", "role", "tabIndex"] }, { kind: "component", type: StreamingFeedbackComponent, selector: "praxis-ai-streaming-feedback", inputs: ["title", "displayText", "isThinking"] }, { kind: "pipe", type: i1$3.JsonPipe, name: "json" }] });
|
|
10866
|
+
`, isInline: true, styles: [".ai-wizard-container{position:relative;padding-bottom:0;max-height:85vh;display:flex;flex-direction:column}.wizard-title{display:flex;align-items:center;gap:12px;color:#673ab7;margin:0;padding:20px 24px;border-bottom:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface);z-index:1}.step-badge{font-size:12px;background:#673ab71a;padding:2px 8px;border-radius:12px;margin-left:auto}.ai-icon{color:#673ab7}.wizard-content{flex:1;overflow-y:auto;padding:0;min-height:300px}.step-prompt,.step-review{padding:20px 24px}.intro-text{color:var(--md-sys-color-on-surface-variant);margin-bottom:24px;font-size:14px}.form-row{display:flex;gap:16px;margin-bottom:8px}.type-select{width:200px}.prompt-input{width:100%}.properties-panel{margin-top:16px;box-shadow:none;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px!important}.suggestions-card{border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;padding:12px;margin:12px 0 4px;background:var(--md-sys-color-surface-container-low)}.suggestions-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px;gap:8px}.suggestions-header .title{display:flex;align-items:center;gap:8px;font-weight:600;font-size:14px}.suggestions-body{display:flex;flex-wrap:wrap;gap:8px}.suggestion-chip{cursor:pointer;max-width:100%;white-space:normal;line-height:1.3}.suggestions-loading,.suggestions-empty{display:flex;align-items:center;gap:8px;color:var(--md-sys-color-on-surface-variant);font-size:13px}.properties-list{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:8px;padding:8px 0}.prop-item{font-size:12px;display:flex;align-items:center;gap:6px}.prop-name{font-weight:600;font-family:monospace}.prop-type{color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container);padding:2px 6px;border-radius:4px;font-size:10px}.prop-desc{color:var(--md-sys-color-on-surface-variant);font-style:italic}.review-header{margin-bottom:20px;border-bottom:1px solid var(--md-sys-color-outline-variant);padding-bottom:12px}.review-header h3{margin:0 0 8px;font-size:18px}.target-badges{display:flex;gap:8px}.badge-type{background:#e0e0e0;color:#424242;padding:2px 8px;border-radius:4px;font-size:11px;text-transform:uppercase;font-weight:700}.badge-id{background:var(--md-sys-color-secondary-container);color:var(--md-sys-color-on-secondary-container);padding:2px 8px;border-radius:4px;font-size:12px;font-family:monospace}.warnings-box{background:#fff8e1;border:1px solid #ffecb3;border-radius:8px;padding:12px;margin-bottom:16px}.warning-title{display:flex;align-items:center;gap:8px;color:#f57f17;font-weight:600;font-size:13px;margin-bottom:8px}.warning-title mat-icon{font-size:18px;width:18px;height:18px}.warning-list{margin:0;padding-left:24px;font-size:13px;color:#5d4037}.summary-view{padding:16px;background:var(--md-sys-color-surface-container-low);border-radius:8px;margin-top:12px}.summary-row{margin-bottom:12px}.summary-row:last-child{margin-bottom:0}.label{display:block;font-size:11px;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant);margin-bottom:4px}.value{font-size:14px}.value.condition{font-family:monospace;color:var(--md-sys-color-primary);background:#00000008;padding:2px 4px;border-radius:4px}.props-grid{display:flex;flex-wrap:wrap;gap:12px}.prop-pair{background:#fff;border:1px solid var(--md-sys-color-outline-variant);padding:4px 8px;border-radius:4px;font-size:13px}.p-key{font-weight:600;margin-right:4px}.p-val{color:var(--md-sys-color-primary)}.json-preview{background:#f5f5f5;padding:12px;border-radius:8px;font-size:12px;max-height:300px;overflow:auto;margin-top:12px}.error-box{margin-top:16px;padding:12px;background-color:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container);border-radius:8px;display:flex;align-items:flex-start;gap:12px;font-size:13px}.ai-processing-overlay{position:absolute;inset:0;background:#ffffffd9;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:10;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:24px;border-radius:8px}.sparkle-icon{font-size:48px;width:48px;height:48px;color:#673ab7;animation:ai-pulse 2s infinite;z-index:2}.ai-pulse-ring{position:absolute;width:80px;height:80px;border-radius:50%;background:radial-gradient(circle,#673ab733,#673ab700 70%);animation:ai-ripple 2s infinite;z-index:1}.processing-text{text-align:center;z-index:2}.processing-text h3{margin:0 0 8px;color:#311b92;font-size:18px;font-weight:500}.fade-text{margin:0;color:#673ab7;font-size:14px;font-style:italic;min-height:20px;animation:text-fade .5s ease-in-out}@keyframes ai-pulse{0%{transform:scale(1);opacity:1;text-shadow:0 0 10px rgba(103,58,183,.5)}50%{transform:scale(1.1);opacity:.8;text-shadow:0 0 20px rgba(103,58,183,.8)}to{transform:scale(1);opacity:1;text-shadow:0 0 10px rgba(103,58,183,.5)}}@keyframes ai-ripple{0%{transform:scale(.8);opacity:.6}to{transform:scale(2.5);opacity:0}}@keyframes text-fade{0%{opacity:0;transform:translateY(5px)}to{opacity:1;transform:translateY(0)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.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: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1$1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1$1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1$1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1$1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i9.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i9.MatLabel, selector: "mat-label" }, { kind: "directive", type: i9.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i10$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i11.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i11.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i7.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "ngmodule", type: MatSnackBarModule }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i13.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i13.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i13.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i14.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i14.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i15.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["role", "id", "aria-label", "aria-description", "value", "color", "removable", "highlighted", "disableRipple", "disabled"], outputs: ["removed", "destroyed"], exportAs: ["matChip"] }, { kind: "component", type: i15.MatChipSet, selector: "mat-chip-set", inputs: ["disabled", "role", "tabIndex"] }, { kind: "component", type: StreamingFeedbackComponent, selector: "praxis-ai-streaming-feedback", inputs: ["title", "displayText", "isThinking"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }, { kind: "pipe", type: i1$3.JsonPipe, name: "json" }] });
|
|
10698
10867
|
}
|
|
10699
10868
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AiRuleWizardDialogComponent, decorators: [{
|
|
10700
10869
|
type: Component,
|
|
@@ -10712,7 +10881,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
10712
10881
|
MatExpansionModule,
|
|
10713
10882
|
MatTabsModule,
|
|
10714
10883
|
MatChipsModule,
|
|
10715
|
-
StreamingFeedbackComponent
|
|
10884
|
+
StreamingFeedbackComponent,
|
|
10885
|
+
PraxisIconButtonComponent,
|
|
10716
10886
|
], template: `
|
|
10717
10887
|
<div class="ai-wizard-container">
|
|
10718
10888
|
<h2 mat-dialog-title class="wizard-title">
|
|
@@ -10760,9 +10930,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
10760
10930
|
<mat-icon>lightbulb</mat-icon>
|
|
10761
10931
|
Sugestões da IA
|
|
10762
10932
|
</div>
|
|
10763
|
-
<button
|
|
10764
|
-
|
|
10765
|
-
|
|
10933
|
+
<button
|
|
10934
|
+
praxisIconButton="refresh"
|
|
10935
|
+
size="dense"
|
|
10936
|
+
type="button"
|
|
10937
|
+
aria-label="Atualizar sugestões da IA"
|
|
10938
|
+
(click)="reloadSuggestions()"
|
|
10939
|
+
[disabled]="loadingSuggestions"
|
|
10940
|
+
></button>
|
|
10766
10941
|
</div>
|
|
10767
10942
|
@if (!loadingSuggestions && suggestions.length > 0) {
|
|
10768
10943
|
<div class="suggestions-body">
|
|
@@ -10948,4 +11123,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
10948
11123
|
* Generated bundle index. Do not edit.
|
|
10949
11124
|
*/
|
|
10950
11125
|
|
|
10951
|
-
export { AI_BACKEND_CONFIG_STORE, AI_BACKEND_ENDPOINTS, AI_BACKEND_STORAGE_OPTIONS, AI_CONTRACT_SCHEMA_HASH, AI_CONTRACT_VERSION, AI_INTENT_CONTRACT_SCHEMA_HASH, AI_INTENT_CONTRACT_VERSION, AI_STREAM_EVENT_SCHEMA_VERSION, AI_STREAM_EVENT_TYPES, AgenticAuthoringTurnClientService, AiBackendApiService, AiPatchStreamConnectionError, AiResponseValidatorService, AiRuleWizardDialogComponent, BaseAiAdapter, PRAXIS_ASSISTANT_CONTEXT_ATTACHMENT_LIMIT, PRAXIS_ASSISTANT_CONTEXT_ITEM_LIMIT, PRAXIS_ASSISTANT_CONTEXT_SCHEMA_FIELD_LIMIT, PRAXIS_ASSISTANT_CONTEXT_TEXT_LIMIT, PRAXIS_ASSISTANT_VOICE_INPUT_MODE, PRAXIS_ASSISTANT_VOICE_LANGUAGE, PRAXIS_AUTHORING_SCOPE_POLICY_KIND, PRAXIS_AUTHORING_SCOPE_POLICY_VERSION, PraxisAi, PraxisAiAssistantComponent, PraxisAiAssistantDockComponent, PraxisAiAssistantSessionHostComponent, PraxisAiAssistantShellComponent, PraxisAiService, PraxisAssistantSessionRegistryService, PraxisAssistantTurnController, PraxisAssistantTurnOrchestratorService, SchemaMinifierService, createAuthoringScopePolicyContext, createAuthoringScopePolicySystemMessage, createComponentAuthoringContext, createPraxisAssistantViewportLayout, normalizeAuthoringPrompt, normalizePraxisAssistantAttachmentSummary, normalizePraxisAssistantContextSnapshot, sanitizePraxisAssistantText, shouldRoutePromptToGovernedDecision, submitPraxisAssistantQuickReply, toAiJsonObject, toPraxisAssistantClarificationOption, toPraxisAssistantConversationMessages, withAuthoringScopePolicy, withAuthoringScopePolicyContextHints, withAuthoringScopePolicyMessage };
|
|
11126
|
+
export { AI_BACKEND_CONFIG_STORE, AI_BACKEND_ENDPOINTS, AI_BACKEND_STORAGE_OPTIONS, AI_CONTRACT_SCHEMA_HASH, AI_CONTRACT_VERSION, AI_INTENT_CONTRACT_SCHEMA_HASH, AI_INTENT_CONTRACT_VERSION, AI_STREAM_EVENT_SCHEMA_VERSION, AI_STREAM_EVENT_TYPES, AgenticAuthoringTurnClientService, AiBackendApiService, AiPatchStreamConnectionError, AiResponseValidatorService, AiRuleWizardDialogComponent, BaseAiAdapter, PRAXIS_ASSISTANT_CONTEXT_ATTACHMENT_LIMIT, PRAXIS_ASSISTANT_CONTEXT_ITEM_LIMIT, PRAXIS_ASSISTANT_CONTEXT_SCHEMA_FIELD_LIMIT, PRAXIS_ASSISTANT_CONTEXT_TEXT_LIMIT, PRAXIS_ASSISTANT_VOICE_INPUT_MODE, PRAXIS_ASSISTANT_VOICE_LANGUAGE, PRAXIS_AUTHORING_SCOPE_POLICY_KIND, PRAXIS_AUTHORING_SCOPE_POLICY_VERSION, PraxisAi, PraxisAiAssistantComponent, PraxisAiAssistantDockComponent, PraxisAiAssistantSessionHostComponent, PraxisAiAssistantShellComponent, PraxisAiService, PraxisAssistantSessionRegistryService, PraxisAssistantTurnController, PraxisAssistantTurnOrchestratorService, PraxisGovernedAudioTranscriptionService, SchemaMinifierService, createAuthoringScopePolicyContext, createAuthoringScopePolicySystemMessage, createComponentAuthoringContext, createPraxisAssistantViewportLayout, normalizeAuthoringPrompt, normalizePraxisAssistantAttachmentSummary, normalizePraxisAssistantContextSnapshot, sanitizePraxisAssistantText, shouldRoutePromptToGovernedDecision, submitPraxisAssistantQuickReply, toAiJsonObject, toPraxisAssistantClarificationOption, toPraxisAssistantConversationMessages, withAuthoringScopePolicy, withAuthoringScopePolicyContextHints, withAuthoringScopePolicyMessage };
|