Replace literature toggle with 4-button consultation system
Browse files- Remove external literature toggle button from chat UI
- Add contextual 4-button literature consultation system that appears after agent responses
- Skip consultation buttons for first user query, show on subsequent queries
- Implement 4 consultation options: underlying paper, external literature, both sources, skip
- Add proper styling with color-coded buttons in 2x2 grid layout
- Generate synthetic user queries based on button selection
- Maintain compatibility with existing R server literature handling
- chat_ui.R +64 -72
- www/chat_script.js +127 -20
- www/chat_styles.css +75 -15
chat_ui.R
CHANGED
|
@@ -1,73 +1,65 @@
|
|
| 1 |
-
# chat_ui.R
|
| 2 |
-
|
| 3 |
-
library(shiny)
|
| 4 |
-
|
| 5 |
-
# Function to create the chat button UI
|
| 6 |
-
chatButtonUI <- function() {
|
| 7 |
-
actionButton("toggleChatBtn", "Chat", icon = icon("comments"),
|
| 8 |
-
class = "btn-primary chat-toggle-button") # Added a class for styling
|
| 9 |
-
}
|
| 10 |
-
|
| 11 |
-
# Function to create the chat sidebar UI
|
| 12 |
-
chatSidebarUI <- function() {
|
| 13 |
-
sidebar_id_to_use <- "chatSidebar"
|
| 14 |
-
print(paste("--- In chat_ui.R, chatSidebarUI IS DEFINING ID AS:", sidebar_id_to_use, "---")) # New print
|
| 15 |
-
|
| 16 |
-
# Source the warning overlay code
|
| 17 |
-
source("warning_overlay.R", local = TRUE)
|
| 18 |
-
|
| 19 |
-
tagList(
|
| 20 |
-
# Initialize shinyjs (used for disabling inputs and potentially other UI manipulations)
|
| 21 |
-
shinyjs::useShinyjs(),
|
| 22 |
-
|
| 23 |
-
# The old warningOverlayUI() and its specific JS are removed as we shift to chat messages.
|
| 24 |
-
# tags$script(HTML(warningOverlayJS)), # This JS was for the old overlay
|
| 25 |
-
|
| 26 |
-
absolutePanel(
|
| 27 |
-
id = sidebar_id_to_use, # Use the variable here
|
| 28 |
-
class = "chat-sidebar", # Class for styling
|
| 29 |
-
top = 0, right = 0, width = "350px", height = "100%", # Initial position and size
|
| 30 |
-
draggable = FALSE,
|
| 31 |
-
fixed = TRUE, # Make it fixed position
|
| 32 |
-
style = "display: none; background-color: #f8f9fa; border-left: 1px solid #dee2e6; padding: 15px; box-shadow: -2px 0 5px rgba(0,0,0,0.1); z-index: 1050; position: fixed; right: 0; transition: width 0.1s ease-out; min-width: 250px; max-width: 800px;", # Ensure right overlay
|
| 33 |
-
|
| 34 |
-
# Resize handle on the left edge
|
| 35 |
-
div(
|
| 36 |
-
class = "resize-handle",
|
| 37 |
-
style = "position: absolute; left: 0; top: 0; width: 5px; height: 100%; cursor: ew-resize; background-color: transparent; z-index: 1060;"
|
| 38 |
-
),
|
| 39 |
-
|
| 40 |
-
h4("TaijiChat Assistant"),
|
| 41 |
-
hr(),
|
| 42 |
-
div(
|
| 43 |
-
id = "chatMessages",
|
| 44 |
-
class = "chat-messages-area", # For styling the message display
|
| 45 |
-
style = "height: calc(100vh - 200px); overflow-y: auto; border: 1px solid #ccc; padding: 10px; margin-bottom: 10px; background-color: white;"
|
| 46 |
-
# Placeholder for messages
|
| 47 |
-
),
|
| 48 |
-
div(
|
| 49 |
-
class = "
|
| 50 |
-
style = "
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
type = "button",
|
| 66 |
-
class = "close", # Standard Bootstrap close button
|
| 67 |
-
`aria-label` = "Close",
|
| 68 |
-
style = "position: absolute; top: 10px; right: 15px; font-size: 1.5rem; color: #000; opacity: 0.5; background: transparent; border: 0;",
|
| 69 |
-
tags$span(`aria-hidden` = "true", HTML("×"))
|
| 70 |
-
)
|
| 71 |
-
)
|
| 72 |
-
)
|
| 73 |
}
|
|
|
|
| 1 |
+
# chat_ui.R
|
| 2 |
+
|
| 3 |
+
library(shiny)
|
| 4 |
+
|
| 5 |
+
# Function to create the chat button UI
|
| 6 |
+
chatButtonUI <- function() {
|
| 7 |
+
actionButton("toggleChatBtn", "Chat", icon = icon("comments"),
|
| 8 |
+
class = "btn-primary chat-toggle-button") # Added a class for styling
|
| 9 |
+
}
|
| 10 |
+
|
| 11 |
+
# Function to create the chat sidebar UI
|
| 12 |
+
chatSidebarUI <- function() {
|
| 13 |
+
sidebar_id_to_use <- "chatSidebar"
|
| 14 |
+
print(paste("--- In chat_ui.R, chatSidebarUI IS DEFINING ID AS:", sidebar_id_to_use, "---")) # New print
|
| 15 |
+
|
| 16 |
+
# Source the warning overlay code
|
| 17 |
+
source("warning_overlay.R", local = TRUE)
|
| 18 |
+
|
| 19 |
+
tagList(
|
| 20 |
+
# Initialize shinyjs (used for disabling inputs and potentially other UI manipulations)
|
| 21 |
+
shinyjs::useShinyjs(),
|
| 22 |
+
|
| 23 |
+
# The old warningOverlayUI() and its specific JS are removed as we shift to chat messages.
|
| 24 |
+
# tags$script(HTML(warningOverlayJS)), # This JS was for the old overlay
|
| 25 |
+
|
| 26 |
+
absolutePanel(
|
| 27 |
+
id = sidebar_id_to_use, # Use the variable here
|
| 28 |
+
class = "chat-sidebar", # Class for styling
|
| 29 |
+
top = 0, right = 0, width = "350px", height = "100%", # Initial position and size
|
| 30 |
+
draggable = FALSE,
|
| 31 |
+
fixed = TRUE, # Make it fixed position
|
| 32 |
+
style = "display: none; background-color: #f8f9fa; border-left: 1px solid #dee2e6; padding: 15px; box-shadow: -2px 0 5px rgba(0,0,0,0.1); z-index: 1050; position: fixed; right: 0; transition: width 0.1s ease-out; min-width: 250px; max-width: 800px;", # Ensure right overlay
|
| 33 |
+
|
| 34 |
+
# Resize handle on the left edge
|
| 35 |
+
div(
|
| 36 |
+
class = "resize-handle",
|
| 37 |
+
style = "position: absolute; left: 0; top: 0; width: 5px; height: 100%; cursor: ew-resize; background-color: transparent; z-index: 1060;"
|
| 38 |
+
),
|
| 39 |
+
|
| 40 |
+
h4("TaijiChat Assistant"),
|
| 41 |
+
hr(),
|
| 42 |
+
div(
|
| 43 |
+
id = "chatMessages",
|
| 44 |
+
class = "chat-messages-area", # For styling the message display
|
| 45 |
+
style = "height: calc(100vh - 200px); overflow-y: auto; border: 1px solid #ccc; padding: 10px; margin-bottom: 10px; background-color: white;"
|
| 46 |
+
# Placeholder for messages
|
| 47 |
+
),
|
| 48 |
+
div(
|
| 49 |
+
class = "chat-input-area", # For styling input area
|
| 50 |
+
style = "display: flex; align-items: stretch;",
|
| 51 |
+
textInput("chatInput", NULL, placeholder = "Ask something...", width = "calc(100% - 80px)"),
|
| 52 |
+
actionButton("sendChatMsg", "Send", icon = icon("paper-plane"), class = "btn-success", style = "margin-left: 5px;")
|
| 53 |
+
),
|
| 54 |
+
# Close button for the sidebar
|
| 55 |
+
tags$button(
|
| 56 |
+
id = "closeChatSidebarBtn",
|
| 57 |
+
type = "button",
|
| 58 |
+
class = "close", # Standard Bootstrap close button
|
| 59 |
+
`aria-label` = "Close",
|
| 60 |
+
style = "position: absolute; top: 10px; right: 15px; font-size: 1.5rem; color: #000; opacity: 0.5; background: transparent; border: 0;",
|
| 61 |
+
tags$span(`aria-hidden` = "true", HTML("×"))
|
| 62 |
+
)
|
| 63 |
+
)
|
| 64 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 65 |
}
|
www/chat_script.js
CHANGED
|
@@ -112,8 +112,64 @@ window.showFullImage = function(imagePath) {
|
|
| 112 |
$('#fullImageModal').show();
|
| 113 |
}
|
| 114 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 115 |
function initializeChatUI() {
|
| 116 |
var isFirstChatOpenThisSession = true;
|
|
|
|
| 117 |
var isResizing = false;
|
| 118 |
var startX;
|
| 119 |
var startWidth;
|
|
@@ -306,6 +362,10 @@ function initializeChatUI() {
|
|
| 306 |
var $chatMessages = $('#chatMessages');
|
| 307 |
|
| 308 |
var $messageDiv = $('<div></div>').addClass('chat-message').addClass(messageClass);
|
|
|
|
|
|
|
|
|
|
|
|
|
| 309 |
|
| 310 |
if (messageType === 'user') {
|
| 311 |
// For user messages, just append the text directly without animation
|
|
@@ -378,6 +438,17 @@ function initializeChatUI() {
|
|
| 378 |
}
|
| 379 |
$messageDiv.html(messageText);
|
| 380 |
$chatMessages.append($messageDiv);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 381 |
if (autoScrollEnabled) {
|
| 382 |
$chatMessages.scrollTop($chatMessages[0].scrollHeight);
|
| 383 |
}
|
|
@@ -386,6 +457,16 @@ function initializeChatUI() {
|
|
| 386 |
$chatMessages.append($messageDiv);
|
| 387 |
var lines = messageText.split('\n');
|
| 388 |
typeTextLines($messageDiv, lines, '', 5, function() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 389 |
if (autoScrollEnabled) {
|
| 390 |
$chatMessages.scrollTop($chatMessages[0].scrollHeight);
|
| 391 |
}
|
|
@@ -402,6 +483,52 @@ function initializeChatUI() {
|
|
| 402 |
}
|
| 403 |
}
|
| 404 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 405 |
// Thought toggle handler
|
| 406 |
$(document).off('click.thoughtToggle').on('click.thoughtToggle', '.thought-toggle-arrow', function() {
|
| 407 |
var $arrow = $(this);
|
|
@@ -536,24 +663,4 @@ function initializeChatUI() {
|
|
| 536 |
});
|
| 537 |
|
| 538 |
|
| 539 |
-
// Literature toggle handler
|
| 540 |
-
$(document).off('click.literatureToggle').on('click.literatureToggle', '#literatureToggleBtn', function() {
|
| 541 |
-
var $btn = $(this);
|
| 542 |
-
$btn.toggleClass('active');
|
| 543 |
-
|
| 544 |
-
var isEnabled = $btn.hasClass('active');
|
| 545 |
-
Shiny.setInputValue("literature_search_enabled", isEnabled, {priority: "event"});
|
| 546 |
-
|
| 547 |
-
// Update button text/icon based on state
|
| 548 |
-
if (isEnabled) {
|
| 549 |
-
$btn.html('<i class="fa fa-search"></i> External Literature (ON)');
|
| 550 |
-
} else {
|
| 551 |
-
$btn.html('<i class="fa fa-search"></i> External Literature (OFF)');
|
| 552 |
-
}
|
| 553 |
-
});
|
| 554 |
-
|
| 555 |
-
// Initialize button state (default: disabled)
|
| 556 |
-
setTimeout(function() {
|
| 557 |
-
Shiny.setInputValue("literature_search_enabled", false);
|
| 558 |
-
}, 100);
|
| 559 |
}
|
|
|
|
| 112 |
$('#fullImageModal').show();
|
| 113 |
}
|
| 114 |
|
| 115 |
+
// Global function to add literature consultation buttons
|
| 116 |
+
window.addLiteratureConsultationButtons = function() {
|
| 117 |
+
console.log("Adding literature consultation buttons");
|
| 118 |
+
|
| 119 |
+
var $chatMessages = $('#chatMessages');
|
| 120 |
+
if (!$chatMessages.length) {
|
| 121 |
+
console.error("Chat messages container not found");
|
| 122 |
+
return;
|
| 123 |
+
}
|
| 124 |
+
|
| 125 |
+
// Add consultation message
|
| 126 |
+
var $consultationMsg = $('<div></div>').addClass('chat-message agent-message consultation-message');
|
| 127 |
+
$consultationMsg.text("Would you like to consult the underlying paper this website is based on, search external literature, try both sources, or skip additional research?");
|
| 128 |
+
$chatMessages.append($consultationMsg);
|
| 129 |
+
|
| 130 |
+
// Add button container
|
| 131 |
+
var $buttonContainer = $('<div></div>').addClass('literature-consultation-buttons');
|
| 132 |
+
|
| 133 |
+
// Create the 4 buttons
|
| 134 |
+
var $btnUnderlying = $('<button></button>')
|
| 135 |
+
.addClass('consultation-btn btn-underlying')
|
| 136 |
+
.text('Consult Underlying Paper')
|
| 137 |
+
.data('query-type', 'underlying');
|
| 138 |
+
|
| 139 |
+
var $btnExternal = $('<button></button>')
|
| 140 |
+
.addClass('consultation-btn btn-external')
|
| 141 |
+
.text('Search External Literature')
|
| 142 |
+
.data('query-type', 'external');
|
| 143 |
+
|
| 144 |
+
var $btnBoth = $('<button></button>')
|
| 145 |
+
.addClass('consultation-btn btn-both')
|
| 146 |
+
.text('Try Both Sources')
|
| 147 |
+
.data('query-type', 'both');
|
| 148 |
+
|
| 149 |
+
var $btnSkip = $('<button></button>')
|
| 150 |
+
.addClass('consultation-btn btn-skip')
|
| 151 |
+
.text('Skip Additional Research')
|
| 152 |
+
.data('query-type', 'skip');
|
| 153 |
+
|
| 154 |
+
// Add buttons to container in 2x2 grid
|
| 155 |
+
var $row1 = $('<div></div>').addClass('consultation-row');
|
| 156 |
+
var $row2 = $('<div></div>').addClass('consultation-row');
|
| 157 |
+
|
| 158 |
+
$row1.append($btnUnderlying).append($btnExternal);
|
| 159 |
+
$row2.append($btnBoth).append($btnSkip);
|
| 160 |
+
|
| 161 |
+
$buttonContainer.append($row1).append($row2);
|
| 162 |
+
$chatMessages.append($buttonContainer);
|
| 163 |
+
|
| 164 |
+
// Scroll to bottom
|
| 165 |
+
$chatMessages.scrollTop($chatMessages[0].scrollHeight);
|
| 166 |
+
|
| 167 |
+
console.log("Literature consultation buttons added successfully");
|
| 168 |
+
}
|
| 169 |
+
|
| 170 |
function initializeChatUI() {
|
| 171 |
var isFirstChatOpenThisSession = true;
|
| 172 |
+
var isFirstUserQuery = true; // Track whether user has made their first actual query
|
| 173 |
var isResizing = false;
|
| 174 |
var startX;
|
| 175 |
var startWidth;
|
|
|
|
| 362 |
var $chatMessages = $('#chatMessages');
|
| 363 |
|
| 364 |
var $messageDiv = $('<div></div>').addClass('chat-message').addClass(messageClass);
|
| 365 |
+
|
| 366 |
+
// Show consultation buttons after every non-thinking, non-disclaimer agent response, except for the first user query
|
| 367 |
+
var shouldShowConsultation = (messageType === 'agent' && !isThinkingMessage && !isDisclaimer && !isFirstUserQuery);
|
| 368 |
+
console.log("Message processing:", {messageType, isThinkingMessage, isDisclaimer, isFirstUserQuery, shouldShowConsultation});
|
| 369 |
|
| 370 |
if (messageType === 'user') {
|
| 371 |
// For user messages, just append the text directly without animation
|
|
|
|
| 438 |
}
|
| 439 |
$messageDiv.html(messageText);
|
| 440 |
$chatMessages.append($messageDiv);
|
| 441 |
+
|
| 442 |
+
// Reset first user query flag after first agent response
|
| 443 |
+
if (isFirstUserQuery) {
|
| 444 |
+
console.log("First user query completed, enabling consultation buttons for future queries");
|
| 445 |
+
isFirstUserQuery = false;
|
| 446 |
+
}
|
| 447 |
+
|
| 448 |
+
if (shouldShowConsultation) {
|
| 449 |
+
console.log("Triggering consultation buttons for HTML message");
|
| 450 |
+
window.addLiteratureConsultationButtons();
|
| 451 |
+
}
|
| 452 |
if (autoScrollEnabled) {
|
| 453 |
$chatMessages.scrollTop($chatMessages[0].scrollHeight);
|
| 454 |
}
|
|
|
|
| 457 |
$chatMessages.append($messageDiv);
|
| 458 |
var lines = messageText.split('\n');
|
| 459 |
typeTextLines($messageDiv, lines, '', 5, function() {
|
| 460 |
+
// Reset first user query flag after first agent response
|
| 461 |
+
if (isFirstUserQuery) {
|
| 462 |
+
console.log("First user query completed, enabling consultation buttons for future queries");
|
| 463 |
+
isFirstUserQuery = false;
|
| 464 |
+
}
|
| 465 |
+
|
| 466 |
+
if (shouldShowConsultation) {
|
| 467 |
+
console.log("Triggering consultation buttons for text message");
|
| 468 |
+
window.addLiteratureConsultationButtons();
|
| 469 |
+
}
|
| 470 |
if (autoScrollEnabled) {
|
| 471 |
$chatMessages.scrollTop($chatMessages[0].scrollHeight);
|
| 472 |
}
|
|
|
|
| 483 |
}
|
| 484 |
}
|
| 485 |
|
| 486 |
+
|
| 487 |
+
// Literature consultation button handler
|
| 488 |
+
$(document).off('click.consultationBtn').on('click.consultationBtn', '.consultation-btn', function() {
|
| 489 |
+
console.log("Consultation button clicked");
|
| 490 |
+
var $btn = $(this);
|
| 491 |
+
var queryType = $btn.data('query-type');
|
| 492 |
+
var queryText = '';
|
| 493 |
+
console.log("Button query type:", queryType);
|
| 494 |
+
|
| 495 |
+
// Generate synthetic user query based on button selection
|
| 496 |
+
switch(queryType) {
|
| 497 |
+
case 'underlying':
|
| 498 |
+
queryText = 'Please provide more details from the underlying research paper that supports your previous response.';
|
| 499 |
+
break;
|
| 500 |
+
case 'external':
|
| 501 |
+
queryText = 'Please search external literature to provide additional context and validation for your previous response.';
|
| 502 |
+
break;
|
| 503 |
+
case 'both':
|
| 504 |
+
queryText = 'Please provide both details from the underlying paper and search external literature to give comprehensive context for your previous response.';
|
| 505 |
+
break;
|
| 506 |
+
case 'skip':
|
| 507 |
+
queryText = 'Thank you, no additional research needed.';
|
| 508 |
+
break;
|
| 509 |
+
}
|
| 510 |
+
|
| 511 |
+
// Remove all consultation elements
|
| 512 |
+
$('.consultation-message').remove();
|
| 513 |
+
$('.literature-consultation-buttons').remove();
|
| 514 |
+
|
| 515 |
+
// Add synthetic user message and trigger processing
|
| 516 |
+
if (queryType !== 'skip') {
|
| 517 |
+
addChatMessage(queryText, 'user');
|
| 518 |
+
|
| 519 |
+
// Set literature preference based on button selection
|
| 520 |
+
var literatureEnabled = (queryType === 'external' || queryType === 'both');
|
| 521 |
+
Shiny.setInputValue("literature_search_enabled", literatureEnabled, {priority: "event"});
|
| 522 |
+
|
| 523 |
+
// Send the query
|
| 524 |
+
Shiny.setInputValue("user_chat_message", queryText, {priority: "event"});
|
| 525 |
+
|
| 526 |
+
// Disable input during processing
|
| 527 |
+
$('#chatInput').prop('disabled', true);
|
| 528 |
+
$('#sendChatMsg').prop('disabled', true);
|
| 529 |
+
}
|
| 530 |
+
});
|
| 531 |
+
|
| 532 |
// Thought toggle handler
|
| 533 |
$(document).off('click.thoughtToggle').on('click.thoughtToggle', '.thought-toggle-arrow', function() {
|
| 534 |
var $arrow = $(this);
|
|
|
|
| 663 |
});
|
| 664 |
|
| 665 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 666 |
}
|
www/chat_styles.css
CHANGED
|
@@ -169,29 +169,89 @@
|
|
| 169 |
user-select: none;
|
| 170 |
}
|
| 171 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 172 |
|
| 173 |
-
|
| 174 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 175 |
transition: all 0.3s ease;
|
| 176 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 177 |
}
|
| 178 |
|
| 179 |
-
.
|
| 180 |
-
background-color: #
|
| 181 |
-
color: white
|
| 182 |
-
border-color: #17a2b8;
|
| 183 |
}
|
| 184 |
|
| 185 |
-
.
|
| 186 |
-
background-color:
|
| 187 |
-
|
| 188 |
}
|
| 189 |
|
| 190 |
-
.
|
| 191 |
-
background-color: #
|
| 192 |
color: white;
|
| 193 |
}
|
| 194 |
|
| 195 |
-
.
|
| 196 |
-
|
| 197 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 169 |
user-select: none;
|
| 170 |
}
|
| 171 |
|
| 172 |
+
/* Literature consultation styles */
|
| 173 |
+
.consultation-message {
|
| 174 |
+
background-color: #f0f8ff !important;
|
| 175 |
+
border: 1px solid #87ceeb;
|
| 176 |
+
color: #2f4f4f;
|
| 177 |
+
font-style: italic;
|
| 178 |
+
margin-bottom: 5px !important;
|
| 179 |
+
}
|
| 180 |
+
|
| 181 |
+
.literature-consultation-buttons {
|
| 182 |
+
margin: 10px 0;
|
| 183 |
+
padding: 10px;
|
| 184 |
+
background-color: #f9f9f9;
|
| 185 |
+
border-radius: 10px;
|
| 186 |
+
border: 1px solid #e0e0e0;
|
| 187 |
+
clear: both;
|
| 188 |
+
}
|
| 189 |
+
|
| 190 |
+
.consultation-row {
|
| 191 |
+
display: flex;
|
| 192 |
+
gap: 10px;
|
| 193 |
+
margin-bottom: 10px;
|
| 194 |
+
}
|
| 195 |
+
|
| 196 |
+
.consultation-row:last-child {
|
| 197 |
+
margin-bottom: 0;
|
| 198 |
+
}
|
| 199 |
|
| 200 |
+
.consultation-btn {
|
| 201 |
+
flex: 1;
|
| 202 |
+
padding: 10px 15px;
|
| 203 |
+
border: none;
|
| 204 |
+
border-radius: 8px;
|
| 205 |
+
font-size: 14px;
|
| 206 |
+
font-weight: 500;
|
| 207 |
+
cursor: pointer;
|
| 208 |
transition: all 0.3s ease;
|
| 209 |
+
text-align: center;
|
| 210 |
+
min-height: 45px;
|
| 211 |
+
display: flex;
|
| 212 |
+
align-items: center;
|
| 213 |
+
justify-content: center;
|
| 214 |
}
|
| 215 |
|
| 216 |
+
.btn-underlying {
|
| 217 |
+
background-color: #28a745;
|
| 218 |
+
color: white;
|
|
|
|
| 219 |
}
|
| 220 |
|
| 221 |
+
.btn-underlying:hover {
|
| 222 |
+
background-color: #218838;
|
| 223 |
+
transform: translateY(-2px);
|
| 224 |
}
|
| 225 |
|
| 226 |
+
.btn-external {
|
| 227 |
+
background-color: #007bff;
|
| 228 |
color: white;
|
| 229 |
}
|
| 230 |
|
| 231 |
+
.btn-external:hover {
|
| 232 |
+
background-color: #0056b3;
|
| 233 |
+
transform: translateY(-2px);
|
| 234 |
+
}
|
| 235 |
+
|
| 236 |
+
.btn-both {
|
| 237 |
+
background-color: #ffc107;
|
| 238 |
+
color: #212529;
|
| 239 |
+
}
|
| 240 |
+
|
| 241 |
+
.btn-both:hover {
|
| 242 |
+
background-color: #e0a800;
|
| 243 |
+
transform: translateY(-2px);
|
| 244 |
+
}
|
| 245 |
+
|
| 246 |
+
.btn-skip {
|
| 247 |
+
background-color: #6c757d;
|
| 248 |
+
color: white;
|
| 249 |
+
}
|
| 250 |
+
|
| 251 |
+
.btn-skip:hover {
|
| 252 |
+
background-color: #545b62;
|
| 253 |
+
transform: translateY(-2px);
|
| 254 |
+
}
|
| 255 |
+
|
| 256 |
+
|
| 257 |
+
|