jesus / templates /index.html
TheM1N9
Enhance responsive design in index.html with viewport meta tag and improved media queries. Adjust styles for chat interface and video overlay for better usability on mobile devices.
0c37653
<!DOCTYPE html>
<html>
<head>
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
/>
<title>Divine Talk</title>
<link
href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:wght@400;600&family=Open+Sans:wght@400;600&display=swap"
rel="stylesheet"
/>
<style>
:root {
--primary-color: #7c5f45;
--secondary-color: #f5e6d3;
--text-color: #2c2c2c;
--background-color: #faf6f0;
--chat-bubble-user: #e3f2fd;
--chat-bubble-bot: #fff;
}
body {
font-family: "Open Sans", sans-serif;
background-color: var(--background-color);
margin: 0;
padding: 0;
color: var(--text-color);
height: 100vh;
display: flex;
flex-direction: column;
}
.container {
max-width: 800px;
margin: 0 auto;
padding: 1rem;
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
}
.header {
text-align: center;
padding: 1rem;
background-color: white;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
position: sticky;
top: 0;
z-index: 100;
}
.header h1 {
font-family: "Cormorant Garamond", serif;
font-size: 2rem;
color: var(--primary-color);
margin: 0;
}
.chat-interface {
margin-top: 0;
position: relative;
z-index: 1;
display: flex;
gap: 2rem;
flex-grow: 1;
margin-top: 2rem;
}
.image-container {
flex: 0 0 300px;
position: sticky;
top: 100px;
align-self: flex-start;
}
.image-container img,
.image-container video {
width: 100%;
border-radius: 15px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.chat-container {
flex: 1;
display: flex;
flex-direction: column;
background: white;
border-radius: 15px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
max-width: 800px;
margin: 0 auto;
width: 100%;
position: relative;
z-index: 2;
/* height: fit-content; */
}
.chat-messages {
flex-grow: 1;
padding: 1.5rem;
overflow-y: auto;
max-height: 60vh;
display: flex;
flex-direction: column;
gap: 1rem;
margin-bottom: 0;
}
.message {
max-width: 80%;
padding: 1rem;
border-radius: 15px;
position: relative;
animation: fadeIn 0.3s ease;
}
.message.user {
background-color: var(--chat-bubble-user);
align-self: flex-end;
border-bottom-right-radius: 5px;
}
.message.bot {
background-color: var(--chat-bubble-bot);
align-self: flex-start;
border-bottom-left-radius: 5px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.input-container {
padding: 1rem;
border-top: 1px solid #eee;
display: flex;
gap: 1rem;
align-items: center;
background: white;
border-radius: 0 0 15px 15px;
margin-top: auto;
}
textarea {
flex-grow: 1;
padding: 0.8rem;
border: 2px solid var(--secondary-color);
border-radius: 25px;
font-size: 1rem;
resize: none;
height: 24px;
min-height: 24px;
max-height: 24px;
line-height: 24px;
font-family: "Open Sans", sans-serif;
transition: all 0.3s ease;
overflow-y: hidden;
}
textarea:focus {
outline: none;
border-color: var(--primary-color);
}
button {
background-color: var(--primary-color);
color: white;
border: none;
padding: 0.8rem 1.5rem;
border-radius: 25px;
font-size: 1rem;
cursor: pointer;
transition: background-color 0.3s ease;
font-weight: 600;
white-space: nowrap;
}
button:hover {
background-color: #6a503a;
}
button:disabled {
background-color: #cccccc;
cursor: not-allowed;
}
.loading {
display: none;
padding: 1rem;
text-align: center;
color: var(--primary-color);
}
.loading::after {
content: "...";
animation: dots 1.5s steps(5, end) infinite;
}
@keyframes dots {
0%,
20% {
content: ".";
}
40% {
content: "..";
}
60%,
100% {
content: "...";
}
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@media (max-width: 768px) {
.chat-interface {
flex-direction: column;
}
.image-container {
position: static;
max-width: 200px;
margin: 0 auto;
}
.message {
max-width: 90%;
}
}
.video-overlay {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 1000px;
height: 540px;
z-index: 1;
display: none;
background: rgba(255, 255, 255, 0.9);
border-radius: 15px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
transition: all 0.3s ease;
}
@media (max-width: 768px) {
.video-overlay {
width: 300px;
height: 500px;
}
}
@media (max-width: 480px) {
.video-overlay {
width: 225px;
height: 400px;
}
}
.video-overlay video {
width: 100%;
height: 100%;
border-radius: 15px;
object-fit: cover;
}
.chat-container {
flex: 1;
max-width: 800px;
margin: 0 auto;
width: 100%;
}
.chat-interface {
gap: 0;
}
/* @keyframes fadeInScale {
from {
opacity: 0;
transform: translate(-50%, -40%);
scale: 0.8;
}
to {
opacity: 1;
transform: translate(-50%, -50%);
scale: 1;
}
} */
.video-overlay.active {
display: block;
animation: fadeInScale 0.3s ease forwards;
}
@media (max-width: 768px) {
.container {
padding: 0.5rem;
height: 100%;
width: auto;
}
.chat-interface {
flex-direction: column;
margin-top: 1rem;
}
.chat-container {
max-width: 100%;
margin: 0;
}
.chat-messages {
max-height: 70vh;
padding: 1rem;
}
.message {
max-width: 85%;
padding: 0.8rem;
}
.input-container {
padding: 0.8rem;
}
textarea {
padding: 0.6rem;
font-size: 15px;
}
button {
padding: 0.6rem 1.2rem;
font-size: 0.9rem;
}
}
@media (max-width: 480px) {
.header h1 {
font-size: 1.5rem;
}
.message {
max-width: 90%;
padding: 0.7rem;
font-size: 0.9rem;
}
.input-container {
gap: 0.5rem;
}
button {
padding: 0.6rem 1rem;
font-size: 0.85rem;
}
}
</style>
</head>
<body>
<div class="header">
<h1>Divine Talk</h1>
</div>
<div class="container">
<div class="chat-interface">
<div class="chat-container">
<div id="chatMessages" class="chat-messages">
<div class="message bot">
Peace be with you. How may I guide you today?
</div>
</div>
<div id="loading" class="loading">Receiving wisdom</div>
<div class="input-container">
<textarea
id="userInput"
placeholder="What would you like to ask?"
rows="1"
aria-label="Your message"
></textarea>
<button onclick="processInput()">Ask in Faith</button>
</div>
</div>
</div>
<div id="videoOverlay" class="video-overlay">
<video id="displayVideo" autoplay muted loop>
<source src="" type="video/mp4" />
</video>
</div>
<audio id="responseAudio" style="display: none"></audio>
</div>
<script>
const textarea = document.getElementById("userInput");
const chatMessages = document.getElementById("chatMessages");
// Remove the auto-resize event listener and replace with character limit
textarea.addEventListener("input", function () {
// Optional: Add character limit if needed
const maxLength = 200; // or whatever limit you want
if (this.value.length > maxLength) {
this.value = this.value.slice(0, maxLength);
}
});
function addMessage(text, isUser) {
const messageDiv = document.createElement("div");
messageDiv.className = `message ${isUser ? "user" : "bot"}`;
messageDiv.textContent = text;
chatMessages.appendChild(messageDiv);
chatMessages.scrollTop = chatMessages.scrollHeight;
}
function getRandomSpeakingVideo() {
const videos = ["/static/speaking_1.mp4", "/static/speaking_2.mp4"];
const randomIndex = Math.floor(Math.random() * videos.length);
return videos[randomIndex];
}
function processInput() {
const userInput = document.getElementById("userInput").value;
if (!userInput.trim()) return;
addMessage(userInput, true);
const loading = document.getElementById("loading");
const button = document.querySelector("button");
loading.style.display = "block";
button.disabled = true;
const formData = new FormData();
formData.append("text", userInput);
textarea.value = "";
textarea.style.height = "24px";
fetch("/process", {
method: "POST",
body: formData,
})
.then((response) => response.json())
.then((data) => {
addMessage(data.text, false);
const audio = document.getElementById("responseAudio");
const newAudio = audio.cloneNode(true);
newAudio.src = data.audio_url;
audio.parentNode.replaceChild(newAudio, audio);
const videoOverlay = document.getElementById("videoOverlay");
const video = document.getElementById("displayVideo");
newAudio.onplay = function () {
// Show and play random video
video.src = getRandomSpeakingVideo();
video.play();
videoOverlay.classList.add("active");
};
newAudio.onended = function () {
// Hide video overlay
videoOverlay.classList.remove("active");
setTimeout(() => {
video.src = ""; // Clear video source after animation
}, 300);
};
newAudio.play();
})
.finally(() => {
loading.style.display = "none";
button.disabled = false;
});
}
// Allow Enter key to submit
textarea.addEventListener("keypress", function (e) {
if (e.key === "Enter" && !e.shiftKey) {
e.preventDefault();
processInput();
}
});
</script>
</body>
</html>