iatoolkit 0.60.2__py3-none-any.whl → 0.62.0__py3-none-any.whl
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.
Potentially problematic release.
This version of iatoolkit might be problematic. Click here for more details.
- iatoolkit/common/routes.py +6 -3
- iatoolkit/common/util.py +0 -6
- iatoolkit/iatoolkit.py +1 -1
- iatoolkit/services/auth_service.py +1 -1
- iatoolkit/static/js/chat_main.js +5 -152
- iatoolkit/static/js/chat_prompt_manager.js +94 -0
- iatoolkit/static/styles/chat_iatoolkit.css +103 -16
- iatoolkit/static/styles/chat_modal.css +6 -4
- iatoolkit/static/styles/landing_page.css +120 -172
- iatoolkit/templates/_company_header.html +21 -0
- iatoolkit/templates/base.html +2 -0
- iatoolkit/templates/change_password.html +3 -3
- iatoolkit/templates/chat.html +72 -83
- iatoolkit/templates/error.html +45 -8
- iatoolkit/templates/forgot_password.html +10 -12
- iatoolkit/templates/index.html +61 -78
- iatoolkit/templates/signup.html +12 -10
- iatoolkit/views/change_password_view.py +1 -1
- iatoolkit/views/forgot_password_view.py +1 -1
- iatoolkit/views/home_view.py +69 -0
- iatoolkit/views/index_view.py +5 -34
- iatoolkit/views/logout_api_view.py +1 -1
- iatoolkit/views/signup_view.py +1 -1
- iatoolkit/views/verify_user_view.py +8 -2
- {iatoolkit-0.60.2.dist-info → iatoolkit-0.62.0.dist-info}/METADATA +1 -1
- {iatoolkit-0.60.2.dist-info → iatoolkit-0.62.0.dist-info}/RECORD +28 -28
- iatoolkit/templates/_branding_styles.html +0 -53
- iatoolkit/templates/_login_widget.html +0 -42
- iatoolkit/templates/_navbar.html +0 -9
- {iatoolkit-0.60.2.dist-info → iatoolkit-0.62.0.dist-info}/WHEEL +0 -0
- {iatoolkit-0.60.2.dist-info → iatoolkit-0.62.0.dist-info}/top_level.txt +0 -0
iatoolkit/common/routes.py
CHANGED
|
@@ -27,10 +27,13 @@ def register_views(injector, app):
|
|
|
27
27
|
from iatoolkit.views.login_view import LoginView, FinalizeContextView
|
|
28
28
|
from iatoolkit.views.external_login_view import ExternalLoginView, RedeemTokenApiView
|
|
29
29
|
from iatoolkit.views.logout_api_view import LogoutApiView
|
|
30
|
-
|
|
30
|
+
from iatoolkit.views.home_view import HomeView
|
|
31
31
|
|
|
32
32
|
# iatoolkit home page
|
|
33
|
-
app.add_url_rule('
|
|
33
|
+
app.add_url_rule('/', view_func=IndexView.as_view('index'))
|
|
34
|
+
|
|
35
|
+
# company home view
|
|
36
|
+
app.add_url_rule('/<company_short_name>/home', view_func=HomeView.as_view('home'))
|
|
34
37
|
|
|
35
38
|
# login for the iatoolkit integrated frontend
|
|
36
39
|
app.add_url_rule('/<company_short_name>/login', view_func=LoginView.as_view('login'))
|
|
@@ -124,6 +127,6 @@ def register_views(injector, app):
|
|
|
124
127
|
# hacer que la raíz '/' vaya al home de iatoolkit
|
|
125
128
|
@app.route('/')
|
|
126
129
|
def root_redirect():
|
|
127
|
-
return redirect(url_for('index'
|
|
130
|
+
return redirect(url_for('index'))
|
|
128
131
|
|
|
129
132
|
|
iatoolkit/common/util.py
CHANGED
|
@@ -21,10 +21,8 @@ class Utility:
|
|
|
21
21
|
def __init__(self):
|
|
22
22
|
self.encryption_key = os.getenv('FERNET_KEY')
|
|
23
23
|
|
|
24
|
-
|
|
25
24
|
def render_prompt_from_template(self,
|
|
26
25
|
template_pathname: str,
|
|
27
|
-
query: str = None,
|
|
28
26
|
client_data: dict = {},
|
|
29
27
|
**kwargs) -> str:
|
|
30
28
|
|
|
@@ -37,8 +35,6 @@ class Utility:
|
|
|
37
35
|
env = Environment(loader=FileSystemLoader(template_dir))
|
|
38
36
|
template = env.get_template(template_file)
|
|
39
37
|
|
|
40
|
-
kwargs["query"] = query
|
|
41
|
-
|
|
42
38
|
# add all the keys in client_data to kwargs
|
|
43
39
|
kwargs.update(client_data)
|
|
44
40
|
|
|
@@ -53,7 +49,6 @@ class Utility:
|
|
|
53
49
|
def render_prompt_from_string(self,
|
|
54
50
|
template_string: str,
|
|
55
51
|
searchpath: str | list[str] = None,
|
|
56
|
-
query: str = None,
|
|
57
52
|
client_data: dict = {},
|
|
58
53
|
**kwargs) -> str:
|
|
59
54
|
"""
|
|
@@ -76,7 +71,6 @@ class Utility:
|
|
|
76
71
|
env = Environment(loader=loader)
|
|
77
72
|
template = env.from_string(template_string)
|
|
78
73
|
|
|
79
|
-
kwargs["query"] = query
|
|
80
74
|
kwargs.update(client_data)
|
|
81
75
|
|
|
82
76
|
prompt = template.render(**kwargs)
|
iatoolkit/iatoolkit.py
CHANGED
|
@@ -19,7 +19,7 @@ from werkzeug.middleware.proxy_fix import ProxyFix
|
|
|
19
19
|
from injector import Binder, Injector, singleton
|
|
20
20
|
from importlib.metadata import version as _pkg_version, PackageNotFoundError
|
|
21
21
|
|
|
22
|
-
IATOOLKIT_VERSION = "0.
|
|
22
|
+
IATOOLKIT_VERSION = "0.62.0"
|
|
23
23
|
|
|
24
24
|
# global variable for the unique instance of IAToolkit
|
|
25
25
|
_iatoolkit_instance: Optional['IAToolkit'] = None
|
|
@@ -110,7 +110,7 @@ class AuthService:
|
|
|
110
110
|
return {
|
|
111
111
|
"success": True,
|
|
112
112
|
"company_short_name": session_info['company_short_name'],
|
|
113
|
-
"user_identifier": session_info['user_identifier']
|
|
113
|
+
"user_identifier": session_info['user_identifier'],
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
# --- Priority 2: Check for a valid API Key in headers ---
|
iatoolkit/static/js/chat_main.js
CHANGED
|
@@ -4,43 +4,22 @@ let abortController = null;
|
|
|
4
4
|
let selectedPrompt = null; // Will hold a lightweight prompt object
|
|
5
5
|
|
|
6
6
|
$(document).ready(function () {
|
|
7
|
-
//
|
|
7
|
+
// Si viene un Token retornado por login con APY-KEY se gatilla el redeem a una sesion de flask
|
|
8
8
|
if (window.redeemToken) {
|
|
9
|
-
const url =
|
|
9
|
+
const url = '/api/redeem_token';
|
|
10
10
|
// No await: dejamos que callToolkit maneje todo internamente
|
|
11
11
|
callToolkit(url, {'token': window.redeemToken}, "POST").catch(() => {});
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
// ---
|
|
14
|
+
// --- chat main event hadlers ---
|
|
15
15
|
$('#send-button').on('click', handleChatMessage);
|
|
16
16
|
$('#stop-button').on('click', abortCurrentRequest);
|
|
17
17
|
if (window.sendButtonColor)
|
|
18
18
|
$('#send-button i').css('color', window.sendButtonColor);
|
|
19
19
|
|
|
20
|
-
// --- PROMPT ASSISTANT FUNCTIONALITY ---
|
|
21
|
-
$('.input-area').on('click', '.dropdown-menu a.dropdown-item', function (event) {
|
|
22
|
-
event.preventDefault();
|
|
23
|
-
const promptData = $(this).data();
|
|
24
|
-
|
|
25
|
-
const promptObject = {
|
|
26
|
-
prompt: promptData.promptName,
|
|
27
|
-
description: promptData.promptDescription,
|
|
28
|
-
custom_fields: typeof promptData.customFields === 'string' ? JSON.parse(promptData.customFields) : promptData.customFields
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
selectPrompt(promptObject);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
// Handles the 'clear' button for the prompt selector
|
|
35
|
-
$('#clear-selection-button').on('click', function() {
|
|
36
|
-
resetPromptSelection();
|
|
37
|
-
updateSendButtonState();
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
// --- TEXTAREA FUNCTIONALITY ---
|
|
41
|
-
const questionTextarea = $('#question');
|
|
42
20
|
|
|
43
21
|
// Handles Enter key press to send a message
|
|
22
|
+
const questionTextarea = $('#question');
|
|
44
23
|
questionTextarea.on('keypress', function (event) {
|
|
45
24
|
if (event.key === 'Enter' && !event.shiftKey) {
|
|
46
25
|
event.preventDefault();
|
|
@@ -60,71 +39,8 @@ $(document).ready(function () {
|
|
|
60
39
|
|
|
61
40
|
// Set the initial disabled state of the send button
|
|
62
41
|
updateSendButtonState();
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Handles the selection of a prompt from the dropdown.
|
|
68
|
-
* @param {object} prompt The prompt object read from data attributes.
|
|
69
|
-
*/
|
|
70
|
-
function selectPrompt(prompt) {
|
|
71
|
-
selectedPrompt = prompt;
|
|
72
|
-
|
|
73
|
-
// Update the dropdown button to show the selected prompt's description
|
|
74
|
-
$('#prompt-select-button').text(prompt.description).addClass('item-selected');
|
|
75
|
-
$('#clear-selection-button').show();
|
|
76
|
-
|
|
77
|
-
// Clear the main textarea, as we are now in "prompt mode"
|
|
78
|
-
$('#question').val('');
|
|
79
|
-
autoResizeTextarea($('#question')[0]); // Reset height after clearing
|
|
80
|
-
|
|
81
|
-
// Store values in hidden fields for backward compatibility or other uses
|
|
82
|
-
$('#prompt-select-value').val(prompt.prompt);
|
|
83
|
-
$('#prompt-select-description').val(prompt.description);
|
|
84
|
-
|
|
85
|
-
// Render the dynamic input fields required by the selected prompt
|
|
86
|
-
renderDynamicInputs(prompt.custom_fields || []);
|
|
87
|
-
updateSendButtonState();
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Resets the prompt selection and clears associated UI elements.
|
|
92
|
-
*/
|
|
93
|
-
function resetPromptSelection() {
|
|
94
|
-
selectedPrompt = null;
|
|
95
|
-
|
|
96
|
-
$('#prompt-select-button').text('Prompts disponibles ....').removeClass('item-selected');
|
|
97
|
-
$('#clear-selection-button').hide();
|
|
98
|
-
$('#prompt-select-value').val('');
|
|
99
|
-
$('#prompt-select-description').val('');
|
|
100
|
-
|
|
101
|
-
// Clear any dynamically generated input fields
|
|
102
|
-
$('#dynamic-inputs-container').empty();
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Renders the custom input fields for the selected prompt.
|
|
107
|
-
* @param {Array<object>} fields The array of custom field configurations.
|
|
108
|
-
*/
|
|
109
|
-
function renderDynamicInputs(fields) {
|
|
110
|
-
const container = $('#dynamic-inputs-container');
|
|
111
|
-
container.empty();
|
|
112
|
-
|
|
113
|
-
const row = $('<div class="row g-2"></div>');
|
|
114
|
-
fields.forEach(field => {
|
|
115
|
-
const colDiv = $('<div class="col-md"></div>');
|
|
116
|
-
const formFloating = $('<div class="form-floating"></div>');
|
|
117
|
-
const input = $(`<input type="${field.type || 'text'}" class="form-control form-control-soft" id="${field.data_key}-id" ">`);
|
|
118
|
-
const label = $(`<label for="${field.data_key}-id">${field.label}</label>`);
|
|
119
|
-
|
|
120
|
-
formFloating.append(input, label);
|
|
121
|
-
colDiv.append(formFloating);
|
|
122
|
-
row.append(colDiv);
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
container.append(row);
|
|
126
|
-
}
|
|
127
42
|
|
|
43
|
+
});
|
|
128
44
|
|
|
129
45
|
|
|
130
46
|
/**
|
|
@@ -162,7 +78,6 @@ const handleChatMessage = async function () {
|
|
|
162
78
|
}
|
|
163
79
|
|
|
164
80
|
// Simplificado: Si no hay mensaje, el 'finally' se encargará de limpiar.
|
|
165
|
-
// Simplemente salimos de la función.
|
|
166
81
|
if (!displayMessage) {
|
|
167
82
|
return;
|
|
168
83
|
}
|
|
@@ -268,27 +183,6 @@ const toggleSendStopButtons = function (showStop) {
|
|
|
268
183
|
$('#stop-button-container').toggle(showStop);
|
|
269
184
|
};
|
|
270
185
|
|
|
271
|
-
/**
|
|
272
|
-
* Resets the prompt selector to its default state.
|
|
273
|
-
*/
|
|
274
|
-
function resetPromptSelect() {
|
|
275
|
-
$('#prompt-select-button').text('Prompts disponibles ....').removeClass('item-selected');
|
|
276
|
-
$('#prompt-select-value').val('');
|
|
277
|
-
$('#prompt-select-description').val('');
|
|
278
|
-
$('#clear-selection-button').hide();
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
/**
|
|
282
|
-
* Resets the company-specific data input field.
|
|
283
|
-
*/
|
|
284
|
-
function resetSpecificDataInput() {
|
|
285
|
-
if (specificDataConfig && specificDataConfig.enabled) {
|
|
286
|
-
const input = $('#' + specificDataConfig.id);
|
|
287
|
-
input.val('').removeClass('has-content');
|
|
288
|
-
$('#clear-' + specificDataConfig.id + '-button').hide();
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
|
|
292
186
|
|
|
293
187
|
/**
|
|
294
188
|
* Generic function to make API calls to the backend.
|
|
@@ -450,44 +344,3 @@ function toBase64(file) {
|
|
|
450
344
|
});
|
|
451
345
|
}
|
|
452
346
|
|
|
453
|
-
/**
|
|
454
|
-
* Displays the document validation results.
|
|
455
|
-
* @param {Array<object>} document_list
|
|
456
|
-
*/
|
|
457
|
-
function display_document_validation(document_list) {
|
|
458
|
-
const requiredFields = ['document_name', 'document_type', 'causes', 'is_valid'];
|
|
459
|
-
for (const doc of document_list) {
|
|
460
|
-
if (!requiredFields.every(field => field in doc)) {
|
|
461
|
-
console.warn("Document with incorrect structure:", doc);
|
|
462
|
-
continue;
|
|
463
|
-
}
|
|
464
|
-
const docValidationSection = $('<div>').addClass('document-section card mt-2 mb-2');
|
|
465
|
-
const cardBody = $('<div>').addClass('card-body');
|
|
466
|
-
const headerDiv = $('<div>').addClass('d-flex justify-content-between align-items-center mb-2');
|
|
467
|
-
const filenameSpan = $(`
|
|
468
|
-
<div>
|
|
469
|
-
<span class="text-primary fw-bold">File: </span>
|
|
470
|
-
<span class="text-secondary">${doc.document_name}</span>
|
|
471
|
-
</div>`);
|
|
472
|
-
const badge_style = doc.is_valid ? 'bg-success' : 'bg-danger';
|
|
473
|
-
const documentBadge = $('<span>')
|
|
474
|
-
.addClass(`badge ${badge_style} p-2`)
|
|
475
|
-
.text(doc.document_type);
|
|
476
|
-
headerDiv.append(filenameSpan).append(documentBadge);
|
|
477
|
-
cardBody.append(headerDiv);
|
|
478
|
-
|
|
479
|
-
if (!doc.is_valid && doc.causes && doc.causes.length > 0) {
|
|
480
|
-
const rejectionSection = $('<div>').addClass('rejection-reasons mt-2');
|
|
481
|
-
rejectionSection.append('<h6 class="text-danger">Rejection Causes:</h6>');
|
|
482
|
-
const causesList = doc.causes.map(cause => `<li class="text-secondary">${cause}</li>`).join('');
|
|
483
|
-
rejectionSection.append(`<ul class="list-unstyled">${causesList}</ul>`);
|
|
484
|
-
cardBody.append(rejectionSection);
|
|
485
|
-
} else if (doc.is_valid) {
|
|
486
|
-
const validSection = $('<div>').addClass('mt-2');
|
|
487
|
-
validSection.append('<p class="text-success fw-bold">Valid document.</p>');
|
|
488
|
-
cardBody.append(validSection);
|
|
489
|
-
}
|
|
490
|
-
docValidationSection.append(cardBody);
|
|
491
|
-
displayBotMessage(docValidationSection);
|
|
492
|
-
}
|
|
493
|
-
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
$(document).ready(function () {
|
|
2
|
+
// --- PROMPT ASSISTANT FUNCTIONALITY ---
|
|
3
|
+
const $promptCollapse = $('#prompt-assistant-collapse');
|
|
4
|
+
|
|
5
|
+
if ($promptCollapse.length) {
|
|
6
|
+
$promptCollapse.on('shown.bs.collapse', function () {
|
|
7
|
+
// Scroll to bottom smoothly when the collapse is shown
|
|
8
|
+
$('html, body').animate(
|
|
9
|
+
{ scrollTop: $(document).height() },
|
|
10
|
+
'slow'
|
|
11
|
+
);
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
$('.input-area').on('click', '.dropdown-menu a.dropdown-item', function (event) {
|
|
16
|
+
event.preventDefault();
|
|
17
|
+
const promptData = $(this).data();
|
|
18
|
+
|
|
19
|
+
const promptObject = {
|
|
20
|
+
prompt: promptData.promptName,
|
|
21
|
+
description: promptData.promptDescription,
|
|
22
|
+
custom_fields: typeof promptData.customFields === 'string' ? JSON.parse(promptData.customFields) : promptData.customFields
|
|
23
|
+
};
|
|
24
|
+
selectPrompt(promptObject);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// Handles the 'clear' button for the prompt selector
|
|
28
|
+
$('#clear-selection-button').on('click', function() {
|
|
29
|
+
resetPromptSelection();
|
|
30
|
+
updateSendButtonState();
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Handles the selection of a prompt from the dropdown.
|
|
36
|
+
* @param {object} prompt The prompt object read from data attributes.
|
|
37
|
+
*/
|
|
38
|
+
function selectPrompt(prompt) {
|
|
39
|
+
selectedPrompt = prompt;
|
|
40
|
+
|
|
41
|
+
// Update the dropdown button to show the selected prompt's description
|
|
42
|
+
$('#prompt-select-button').text(prompt.description).addClass('item-selected');
|
|
43
|
+
$('#clear-selection-button').show();
|
|
44
|
+
|
|
45
|
+
// Clear the main textarea, as we are now in "prompt mode"
|
|
46
|
+
$('#question').val('');
|
|
47
|
+
autoResizeTextarea($('#question')[0]); // Reset height after clearing
|
|
48
|
+
|
|
49
|
+
// Store values in hidden fields for backward compatibility or other uses
|
|
50
|
+
$('#prompt-select-value').val(prompt.prompt);
|
|
51
|
+
$('#prompt-select-description').val(prompt.description);
|
|
52
|
+
|
|
53
|
+
// Render the dynamic input fields required by the selected prompt
|
|
54
|
+
renderDynamicInputs(prompt.custom_fields || []);
|
|
55
|
+
updateSendButtonState();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Resets the prompt selection and clears associated UI elements.
|
|
60
|
+
*/
|
|
61
|
+
function resetPromptSelection() {
|
|
62
|
+
selectedPrompt = null;
|
|
63
|
+
|
|
64
|
+
$('#prompt-select-button').text('Prompts disponibles ....').removeClass('item-selected');
|
|
65
|
+
$('#clear-selection-button').hide();
|
|
66
|
+
$('#prompt-select-value').val('');
|
|
67
|
+
$('#prompt-select-description').val('');
|
|
68
|
+
|
|
69
|
+
// Clear any dynamically generated input fields
|
|
70
|
+
$('#dynamic-inputs-container').empty();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Renders the custom input fields for the selected prompt.
|
|
75
|
+
* @param {Array<object>} fields The array of custom field configurations.
|
|
76
|
+
*/
|
|
77
|
+
function renderDynamicInputs(fields) {
|
|
78
|
+
const container = $('#dynamic-inputs-container');
|
|
79
|
+
container.empty();
|
|
80
|
+
|
|
81
|
+
const row = $('<div class="row g-2"></div>');
|
|
82
|
+
fields.forEach(field => {
|
|
83
|
+
const colDiv = $('<div class="col-md"></div>');
|
|
84
|
+
const formFloating = $('<div class="form-floating"></div>');
|
|
85
|
+
const input = $(`<input type="${field.type || 'text'}" class="form-control form-control-soft" id="${field.data_key}-id" ">`);
|
|
86
|
+
const label = $(`<label for="${field.data_key}-id">${field.label}</label>`);
|
|
87
|
+
|
|
88
|
+
formFloating.append(input, label);
|
|
89
|
+
colDiv.append(formFloating);
|
|
90
|
+
row.append(colDiv);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
container.append(row);
|
|
94
|
+
}
|
|
@@ -24,6 +24,93 @@
|
|
|
24
24
|
box-shadow: 0 2px 8px rgba(0,0,0,0.06); /* Sombra suave y unificada */
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
/* estos estilo aplican a la home page/signup/etc */
|
|
28
|
+
|
|
29
|
+
/* --- Encabezado de Empresa Personalizado (Actualizado) --- */
|
|
30
|
+
.custom-company-header {
|
|
31
|
+
/* Estructura y Posicionamiento */
|
|
32
|
+
display: flex;
|
|
33
|
+
align-items: center;
|
|
34
|
+
justify-content: space-between; /* Para separar el nombre y el "Powered by" */
|
|
35
|
+
height: 78px;
|
|
36
|
+
padding: 0 1.5rem;
|
|
37
|
+
width: 100%;
|
|
38
|
+
margin-bottom: 20px;
|
|
39
|
+
|
|
40
|
+
background-color: var(--brand-primary-color);
|
|
41
|
+
color: var(--brand-text-on-primary);
|
|
42
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/* Estilo específico para el nombre de la marca (Letra más grande) */
|
|
46
|
+
.custom-company-header .brand-name {
|
|
47
|
+
font-size: 1.8rem; /* Tamaño de fuente aumentado */
|
|
48
|
+
font-weight: 600;
|
|
49
|
+
color: inherit;
|
|
50
|
+
text-decoration: none;
|
|
51
|
+
transition: opacity 0.2s ease-in-out;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* Efecto hover para el enlace del nombre de la marca */
|
|
55
|
+
.custom-company-header .brand-name:hover {
|
|
56
|
+
opacity: 0.85;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/* Estilo para el texto "Powered by" --- */
|
|
60
|
+
.custom-company-header .powered-by {
|
|
61
|
+
font-size: 0.9rem;
|
|
62
|
+
font-weight: 400;
|
|
63
|
+
opacity: 0.75; /* Menos prominente que el nombre de la marca */
|
|
64
|
+
color: inherit;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.branded-form-container {
|
|
68
|
+
background-color: #ffffff;
|
|
69
|
+
border: 1px solid #dee2e6;
|
|
70
|
+
border-top: 4px solid #adb5bd;
|
|
71
|
+
border-radius: 0.375rem;
|
|
72
|
+
padding: 2rem;
|
|
73
|
+
box-shadow: 0 4px 12px rgba(0,0,0,0.08);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.branded-headline {
|
|
77
|
+
color: var(--brand-primary-color);
|
|
78
|
+
font-size: 2.5rem;
|
|
79
|
+
font-weight: 700;
|
|
80
|
+
line-height: 1.2;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.text-branded-primary {
|
|
84
|
+
color: var(--brand-primary-color) !important;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
.branded-form-label {
|
|
89
|
+
font-size: 0.85rem;
|
|
90
|
+
font-weight: 600;
|
|
91
|
+
color: #495057; /* Un gris oscuro profesional */
|
|
92
|
+
text-transform: uppercase;
|
|
93
|
+
letter-spacing: 0.05em; /* Un poco de espacio extra entre letras */
|
|
94
|
+
margin-bottom: 0.3rem;
|
|
95
|
+
display: block;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
/* Efecto de foco brandeado para todos los form-control */
|
|
100
|
+
.form-control:focus {
|
|
101
|
+
border-color: var(--brand-primary-color);
|
|
102
|
+
box-shadow: 0 0 0 0.25rem rgba(var(--brand-primary-color-rgb), 0.25); /* Usa la variable RGB para el shadow */
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.branded-form-title {
|
|
106
|
+
color: var(--brand-primary-color);
|
|
107
|
+
font-size: 1.75rem; /* Un tamaño más prominente */
|
|
108
|
+
font-weight: 700; /* Equivalente a fw-bold de Bootstrap */
|
|
109
|
+
text-align: center;
|
|
110
|
+
margin-bottom: 1.5rem; /* Espacio consistente debajo del título */
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
|
|
27
114
|
/* Estilo para la sección del encabezado */
|
|
28
115
|
.company-section {
|
|
29
116
|
border-radius: 0.375rem; /* Mismo radio que .chat-block para consistencia */
|
|
@@ -95,7 +182,6 @@
|
|
|
95
182
|
|
|
96
183
|
/* Estilo del mensaje ingresado por el usuario */
|
|
97
184
|
#chat-container .message {
|
|
98
|
-
margin-top: 10px;
|
|
99
185
|
max-width: 75%;
|
|
100
186
|
min-width: fit-content;
|
|
101
187
|
width: fit-content;
|
|
@@ -105,24 +191,25 @@
|
|
|
105
191
|
align-items: center;
|
|
106
192
|
align-self: flex-end;
|
|
107
193
|
text-align: left;
|
|
108
|
-
padding:
|
|
194
|
+
padding-left: 0.5em;
|
|
195
|
+
color: #202123;
|
|
109
196
|
font-family: Arial, sans-serif;
|
|
110
197
|
font-size: 15px;
|
|
111
|
-
line-height: 1.
|
|
112
|
-
color: #
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
198
|
+
line-height: 1.6;
|
|
199
|
+
background-color: #f7f7f8;
|
|
200
|
+
border: none;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.answer-section {
|
|
204
|
+
align-self: flex-start;
|
|
205
|
+
max-width: 75%;
|
|
206
|
+
padding: 10px 15px;
|
|
207
|
+
font-family: "Inter", Arial, sans-serif;
|
|
208
|
+
font-size: 15px;
|
|
209
|
+
line-height: 1.6;
|
|
210
|
+
word-wrap: break-word;
|
|
211
|
+
}
|
|
117
212
|
|
|
118
|
-
.answer-section {
|
|
119
|
-
color: #202123; /* Texto negro suave */
|
|
120
|
-
font-family: "Inter", Arial, sans-serif; /* Fuente moderna */
|
|
121
|
-
font-size: 16px;
|
|
122
|
-
line-height: 1.6;
|
|
123
|
-
word-wrap: break-word;
|
|
124
|
-
padding-top: 0.5em;
|
|
125
|
-
}
|
|
126
213
|
.error-section {
|
|
127
214
|
align-self: flex-start;
|
|
128
215
|
max-width: 75%;
|
|
@@ -19,8 +19,9 @@
|
|
|
19
19
|
color: var(--brand-text-on-primary);
|
|
20
20
|
}
|
|
21
21
|
.btn-branded-primary:hover {
|
|
22
|
-
|
|
23
|
-
color: var(--brand-
|
|
22
|
+
background-color: var(--brand-text-on-primary);
|
|
23
|
+
color: var(--brand-primary-color);
|
|
24
|
+
border-color: var(--brand-primary-color);
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
.btn-branded-secondary {
|
|
@@ -29,8 +30,9 @@
|
|
|
29
30
|
color: var(--brand-text-on-secondary);
|
|
30
31
|
}
|
|
31
32
|
.btn-branded-secondary:hover {
|
|
32
|
-
|
|
33
|
-
color: var(--brand-
|
|
33
|
+
background-color: var(--brand-text-on-secondary);
|
|
34
|
+
color: var(--brand-secondary-color);
|
|
35
|
+
border-color: var(--brand-secondary-color);
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
/* Estilos para alertas informativas personalizadas */
|