131 lines
6.4 KiB
HTML
131 lines
6.4 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
|
<title>BitSage - CS Learning Companion</title>
|
|
<script src="https://cdn.tailwindcss.com"></script>
|
|
<script>
|
|
tailwind.config = {
|
|
darkMode: 'class',
|
|
theme: {
|
|
extend: {
|
|
colors: {
|
|
primary: {
|
|
50: '#eff6ff',
|
|
100: '#dbeafe',
|
|
200: '#bfdbfe',
|
|
300: '#93c5fd',
|
|
400: '#60a5fa',
|
|
500: '#3b82f6',
|
|
600: '#2563eb',
|
|
700: '#1d4ed8',
|
|
800: '#1e40af',
|
|
900: '#1e3a8a',
|
|
}
|
|
},
|
|
animation: {
|
|
'pulse-slow': 'pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite',
|
|
'fade-in': 'fadeIn 0.6s cubic-bezier(0.16, 1, 0.3, 1) forwards',
|
|
'slide-up': 'slideUp 0.5s cubic-bezier(0.16, 1, 0.3, 1) forwards',
|
|
'bounce-in': 'bounceIn 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards',
|
|
},
|
|
keyframes: {
|
|
fadeIn: {
|
|
'0%': { opacity: '0' },
|
|
'100%': { opacity: '1' },
|
|
},
|
|
slideUp: {
|
|
'0%': { transform: 'translateY(20px)', opacity: '0' },
|
|
'100%': { transform: 'translateY(0)', opacity: '1' },
|
|
},
|
|
bounceIn: {
|
|
'0%': { transform: 'scale(0.9)', opacity: '0' },
|
|
'100%': { transform: 'scale(1)', opacity: '1' },
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
<!-- Direct Favicon Link -->
|
|
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232563eb' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9.5 2A2.5 2.5 0 0 1 12 4.5v15a2.5 2.5 0 0 1-4.96.44 2.5 2.5 0 0 1-2.96-3.08 3 3 0 0 1-.34-5.58 2.5 2.5 0 0 1 1.32-4.24 2.5 2.5 0 0 1 1.32-4.24 2.5 2.5 0 0 1 1.98-3A2.5 2.5 0 0 1 9.5 2Z'/%3E%3Cpath d='M14.5 2A2.5 2.5 0 0 0 12 4.5v15a2.5 2.5 0 0 0 4.96.44 2.5 2.5 0 0 0 2.96-3.08 3 3 0 0 0 .34-5.58 2.5 2.5 0 0 0-1.32-4.24 2.5 2.5 0 0 0-1.98-3A2.5 2.5 0 0 0 14.5 2Z'/%3E%3C/svg%3E" />
|
|
|
|
<!-- PWA Manifest (display: standalone is critical for installability) -->
|
|
<link rel="manifest" href='data:application/json;charset=utf-8,{"name":"BitSage - CS Learning Companion","short_name":"BitSage","start_url":"/","display":"standalone","background_color":"#ffffff","theme_color":"#2563eb","icons":[{"src":"data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 24 24%27 fill=%27none%27 stroke=%27%232563eb%27 stroke-width=%272%27 stroke-linecap=%27round%27 stroke-linejoin=%27round%27%3E%3Cpath d=%27M9.5 2A2.5 2.5 0 0 1 12 4.5v15a2.5 2.5 0 0 1-4.96.44 2.5 2.5 0 0 1-2.96-3.08 3 3 0 0 1-.34-5.58 2.5 2.5 0 0 1 1.32-4.24 2.5 2.5 0 0 1 1.32-4.24 2.5 2.5 0 0 1 1.98-3A2.5 2.5 0 0 1 9.5 2Z%27/%3E%3Cpath d=%27M14.5 2A2.5 2.5 0 0 0 12 4.5v15a2.5 2.5 0 0 0 4.96.44 2.5 2.5 0 0 0 2.96-3.08 3 3 0 0 0 .34-5.58 2.5 2.5 0 0 0-1.32-4.24 2.5 2.5 0 0 0-1.98-3A2.5 2.5 0 0 0 14.5 2Z%27/%3E%3C/svg%3E","type":"image/svg+xml","sizes":"192x192 512x512"}]}' />
|
|
|
|
<style>
|
|
/* Custom scrollbar for webkit */
|
|
::-webkit-scrollbar { width: 6px; height: 6px; }
|
|
::-webkit-scrollbar-track { background: transparent; }
|
|
::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 3px; }
|
|
.dark ::-webkit-scrollbar-thumb { background: #475569; }
|
|
|
|
/* Markdown content styles */
|
|
.markdown-body p { margin-bottom: 0.75em; line-height: 1.6; }
|
|
.markdown-body ul { list-style-type: disc; padding-left: 1.5em; margin-bottom: 0.75em; }
|
|
.markdown-body ol { list-style-type: decimal; padding-left: 1.5em; margin-bottom: 0.75em; }
|
|
.markdown-body pre { background: #f1f5f9; padding: 1em; border-radius: 0.5em; overflow-x: auto; margin-bottom: 1em; }
|
|
.dark .markdown-body pre { background: #1e293b; }
|
|
.markdown-body code { font-family: monospace; background: #e2e8f0; padding: 0.1em 0.3em; border-radius: 0.25em; font-size: 0.9em; }
|
|
.dark .markdown-body code { background: #334155; color: #e2e8f0; }
|
|
.markdown-body pre code { background: transparent; padding: 0; color: inherit; }
|
|
.markdown-body h1, .markdown-body h2, .markdown-body h3 { font-weight: 700; margin-top: 1.5em; margin-bottom: 0.5em; }
|
|
.markdown-body h1 { font-size: 1.5em; }
|
|
.markdown-body h2 { font-size: 1.25em; }
|
|
.markdown-body a { color: #3b82f6; text-decoration: underline; }
|
|
|
|
/* Typing Indicator Animation */
|
|
.typing-indicator {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
padding: 4px 0;
|
|
}
|
|
.typing-indicator span {
|
|
display: inline-block;
|
|
width: 6px;
|
|
height: 6px;
|
|
background-color: #94a3b8; /* slate-400 */
|
|
border-radius: 50%;
|
|
animation: typingBounce 1.4s infinite ease-in-out both;
|
|
}
|
|
.typing-indicator span:nth-child(1) { animation-delay: -0.32s; }
|
|
.typing-indicator span:nth-child(2) { animation-delay: -0.16s; }
|
|
|
|
@keyframes typingBounce {
|
|
0%, 80%, 100% { transform: scale(0); opacity: 0.6; }
|
|
40% { transform: scale(1); opacity: 1; }
|
|
}
|
|
</style>
|
|
<script type="importmap">
|
|
{
|
|
"imports": {
|
|
"react": "https://esm.sh/react@^19.2.3",
|
|
"react-dom/": "https://esm.sh/react-dom@^19.2.3/",
|
|
"react/": "https://esm.sh/react@^19.2.3/",
|
|
"@google/genai": "https://esm.sh/@google/genai@^1.34.0",
|
|
"lucide-react": "https://esm.sh/lucide-react@^0.562.0",
|
|
"react-markdown": "https://esm.sh/react-markdown@^10.1.0",
|
|
"remark-gfm": "https://esm.sh/remark-gfm@^4.0.1",
|
|
"html2canvas": "https://esm.sh/html2canvas@^1.4.1",
|
|
"vite": "https://esm.sh/vite@^7.3.0",
|
|
"@vitejs/plugin-react": "https://esm.sh/@vitejs/plugin-react@^5.1.2"
|
|
}
|
|
}
|
|
</script>
|
|
</head>
|
|
<body class="bg-gray-50 dark:bg-slate-900 text-gray-900 dark:text-gray-100 h-[100dvh] overflow-hidden">
|
|
<div id="root" class="h-full"></div>
|
|
<script type="module" src="/index.tsx"></script>
|
|
<script>
|
|
if ('serviceWorker' in navigator) {
|
|
window.addEventListener('load', () => {
|
|
navigator.serviceWorker.register('./sw.js').catch(err => {
|
|
console.error('SW registration failed:', err);
|
|
});
|
|
});
|
|
}
|
|
</script>
|
|
</body>
|
|
</html> |