Spaces:
Running
Running
how i can give you API?
Browse files- README.md +9 -5
- about.html +107 -0
- api-config.js +45 -0
- components/footer.js +50 -0
- components/navbar.js +80 -0
- index.html +160 -19
- script.js +206 -0
- style.css +41 -18
README.md
CHANGED
|
@@ -1,10 +1,14 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
sdk: static
|
| 7 |
pinned: false
|
|
|
|
|
|
|
| 8 |
---
|
| 9 |
|
| 10 |
-
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
+
title: API Integration Wizards 🧙
|
| 3 |
+
colorFrom: pink
|
| 4 |
+
colorTo: pink
|
| 5 |
+
emoji: 🐳
|
| 6 |
sdk: static
|
| 7 |
pinned: false
|
| 8 |
+
tags:
|
| 9 |
+
- deepsite-v3
|
| 10 |
---
|
| 11 |
|
| 12 |
+
# Welcome to your new DeepSite project!
|
| 13 |
+
This project was created with [DeepSite](https://huggingface.co/deepsite).
|
| 14 |
+
|
about.html
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en" class="dark">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>About - Hanzi Hunter</title>
|
| 7 |
+
<link rel="stylesheet" href="style.css">
|
| 8 |
+
<script src="https://cdn.tailwindcss.com"></script>
|
| 9 |
+
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
|
| 10 |
+
<script src="https://unpkg.com/feather-icons"></script>
|
| 11 |
+
<script>
|
| 12 |
+
tailwind.config = {
|
| 13 |
+
darkMode: 'class',
|
| 14 |
+
theme: {
|
| 15 |
+
extend: {
|
| 16 |
+
colors: {
|
| 17 |
+
primary: '#000000',
|
| 18 |
+
secondary: '#DC2626'
|
| 19 |
+
}
|
| 20 |
+
}
|
| 21 |
+
}
|
| 22 |
+
}
|
| 23 |
+
</script>
|
| 24 |
+
</head>
|
| 25 |
+
<body class="bg-black text-white min-h-screen flex flex-col">
|
| 26 |
+
<custom-navbar></custom-navbar>
|
| 27 |
+
|
| 28 |
+
<main class="flex-1 container mx-auto px-4 py-8">
|
| 29 |
+
<!-- Hero Section -->
|
| 30 |
+
<section class="text-center mb-12">
|
| 31 |
+
<h1 class="text-4xl md:text-6xl font-bold mb-4 bg-gradient-to-r from-white to-red-600 bg-clip-text text-transparent">
|
| 32 |
+
About Hanzi Hunter
|
| 33 |
+
</h1>
|
| 34 |
+
<p class="text-xl text-gray-400">Your ultimate Chinese vocabulary companion</p>
|
| 35 |
+
</section>
|
| 36 |
+
|
| 37 |
+
<!-- Content Section -->
|
| 38 |
+
<section class="max-w-4xl mx-auto">
|
| 39 |
+
<div class="bg-gray-900 rounded-2xl p-8 shadow-2xl border border-red-900">
|
| 40 |
+
<div class="grid md:grid-cols-2 gap-8 items-center">
|
| 41 |
+
<div>
|
| 42 |
+
<h2 class="text-3xl font-bold mb-4">What is Hanzi Hunter?</h2>
|
| 43 |
+
<p class="text-gray-300 mb-6">
|
| 44 |
+
Hanzi Hunter is an intelligent tool designed to help Chinese language learners
|
| 45 |
+
understand the complexity and usage of Chinese vocabulary.
|
| 46 |
+
</p>
|
| 47 |
+
<div class="space-y-4">
|
| 48 |
+
<div class="flex items-start">
|
| 49 |
+
<i data-feather="check-circle" class="w-5 h-5 text-red-500 mr-3 mt-1"></i>
|
| 50 |
+
<div>
|
| 51 |
+
<h3 class="font-semibold text-white">HSK Level Detection</h3>
|
| 52 |
+
<p class="text-gray-400 text-sm">Instantly identify which official HSK level your vocabulary belongs to.</p>
|
| 53 |
+
</div>
|
| 54 |
+
</div>
|
| 55 |
+
<div class="flex items-start">
|
| 56 |
+
<i data-feather="check-circle" class="w-5 h-5 text-red-500 mr-3 mt-1"></i>
|
| 57 |
+
<div>
|
| 58 |
+
<h3 class="font-semibold text-white">Usage Analysis</h3>
|
| 59 |
+
<p class="text-gray-400 text-sm">Learn whether words are formal, informal, common in speech, or mostly written.</p>
|
| 60 |
+
</div>
|
| 61 |
+
</div>
|
| 62 |
+
<div class="flex items-start">
|
| 63 |
+
<i data-feather="check-circle" class="w-5 h-5 text-red-500 mr-3 mt-1"></i>
|
| 64 |
+
<div>
|
| 65 |
+
<h3 class="font-semibold text-white">Style Classification</h3>
|
| 66 |
+
<p class="text-gray-400 text-sm">Understand the appropriate context for using each word.</p>
|
| 67 |
+
</div>
|
| 68 |
+
</div>
|
| 69 |
+
</div>
|
| 70 |
+
</div>
|
| 71 |
+
<div class="text-center">
|
| 72 |
+
<i data-feather="compass" class="w-32 h-32 text-red-500 mx-auto"></i>
|
| 73 |
+
</div>
|
| 74 |
+
</div>
|
| 75 |
+
|
| 76 |
+
<!-- Features Grid -->
|
| 77 |
+
<div class="mt-12 grid md:grid-cols-2 gap-6">
|
| 78 |
+
<div class="bg-gray-800 p-6 rounded-xl border border-red-900">
|
| 79 |
+
<i data-feather="target" class="w-8 h-8 text-red-500 mb-4"></i>
|
| 80 |
+
<h3 class="text-xl font-bold mb-2">Smart Detection</h3>
|
| 81 |
+
<p class="text-gray-400">Our algorithm analyzes Chinese characters and provides instant feedback on their HSK level and usage patterns.</p>
|
| 82 |
+
</div>
|
| 83 |
+
<div class="bg-gray-800 p-6 rounded-xl border border-red-900">
|
| 84 |
+
<i data-feather="book" class="w-8 h-8 text-red-500 mb-4"></i>
|
| 85 |
+
<h3 class="text-xl font-bold mb-2">Learning Focused</h3>
|
| 86 |
+
<p class="text-gray-400">Designed specifically for Chinese language learners at all levels.</p>
|
| 87 |
+
</div>
|
| 88 |
+
</div>
|
| 89 |
+
</section>
|
| 90 |
+
</main>
|
| 91 |
+
|
| 92 |
+
<custom-footer></custom-footer>
|
| 93 |
+
<!-- API Configuration -->
|
| 94 |
+
<script src="api-config.js"></script>
|
| 95 |
+
|
| 96 |
+
<!-- Component Scripts -->
|
| 97 |
+
<script src="components/navbar.js"></script>
|
| 98 |
+
<script src="components/footer.js"></script>
|
| 99 |
+
|
| 100 |
+
<!-- Main Script -->
|
| 101 |
+
<script src="script.js"></script>
|
| 102 |
+
<!-- Feather Icons -->
|
| 103 |
+
<script>
|
| 104 |
+
feather.replace();
|
| 105 |
+
</script>
|
| 106 |
+
</body>
|
| 107 |
+
</html>
|
api-config.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// API Configuration for Hanzi Hunter
|
| 2 |
+
class APIConfig {
|
| 3 |
+
constructor() {
|
| 4 |
+
this.apis = {
|
| 5 |
+
// Free Chinese Dictionary API
|
| 6 |
+
dictionary: {
|
| 7 |
+
url: 'https://api.dictionaryapi.dev/api/v2/entries/zh/',
|
| 8 |
+
method: 'GET'
|
| 9 |
+
},
|
| 10 |
+
// HanziDB API for character information
|
| 11 |
+
hanzi: {
|
| 12 |
+
url: 'https://hanzi-db.herokuapp.com/api/characters/',
|
| 13 |
+
method: 'GET'
|
| 14 |
+
},
|
| 15 |
+
// Mock HSK API (you can replace with real API)
|
| 16 |
+
hsk: {
|
| 17 |
+
url: 'https://jsonplaceholder.typicode.com/posts',
|
| 18 |
+
method: 'GET'
|
| 19 |
+
},
|
| 20 |
+
// Backend API (replace with your actual backend URL)
|
| 21 |
+
backend: {
|
| 22 |
+
url: 'https://your-backend-api.com/api/',
|
| 23 |
+
method: 'POST'
|
| 24 |
+
}
|
| 25 |
+
};
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
// Method to set custom API endpoints
|
| 29 |
+
setAPI(name, url, method = 'GET') {
|
| 30 |
+
this.apis[name] = { url, method };
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
// Method to get API configuration
|
| 34 |
+
getAPI(name) {
|
| 35 |
+
return this.apis[name];
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
// Method to update all API configurations
|
| 39 |
+
updateAPIs(newConfigs) {
|
| 40 |
+
this.apis = { ...this.apis, ...newConfigs };
|
| 41 |
+
}
|
| 42 |
+
}
|
| 43 |
+
|
| 44 |
+
// Create global API config instance
|
| 45 |
+
window.apiConfig = new APIConfig();
|
components/footer.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
class CustomFooter extends HTMLElement {
|
| 2 |
+
connectedCallback() {
|
| 3 |
+
this.attachShadow({ mode: 'open' });
|
| 4 |
+
this.shadowRoot.innerHTML = `
|
| 5 |
+
<style>
|
| 6 |
+
footer {
|
| 7 |
+
background: #000000;
|
| 8 |
+
color: #a3a3a3;
|
| 9 |
+
padding: 2rem;
|
| 10 |
+
text-align: center;
|
| 11 |
+
margin-top: auto;
|
| 12 |
+
border-top: 1px solid #dc2626;
|
| 13 |
+
}
|
| 14 |
+
.footer-content {
|
| 15 |
+
max-width: 1200px;
|
| 16 |
+
margin: 0 auto;
|
| 17 |
+
}
|
| 18 |
+
.social-links {
|
| 19 |
+
display: flex;
|
| 20 |
+
justify-content: center;
|
| 21 |
+
gap: 1rem;
|
| 22 |
+
margin-bottom: 1rem;
|
| 23 |
+
}
|
| 24 |
+
.social-link {
|
| 25 |
+
color: #a3a3a3;
|
| 26 |
+
transition: all 0.3s ease;
|
| 27 |
+
}
|
| 28 |
+
.social-link:hover {
|
| 29 |
+
color: #dc2626;
|
| 30 |
+
transform: translateY(-2px);
|
| 31 |
+
}
|
| 32 |
+
.copyright {
|
| 33 |
+
font-size: 0.875rem;
|
| 34 |
+
}
|
| 35 |
+
</style>
|
| 36 |
+
<footer>
|
| 37 |
+
<div class="footer-content">
|
| 38 |
+
<div class="social-links">
|
| 39 |
+
<a href="#" class="social-link"><i data-feather="github"></i></a>
|
| 40 |
+
<a href="#" class="social-link"><i data-feather="twitter"></i></a>
|
| 41 |
+
<a href="#" class="social-link"><i data-feather="mail"></i></a>
|
| 42 |
+
</div>
|
| 43 |
+
<p class="copyright">© 2024 Hanzi Hunter. All rights reserved.</p>
|
| 44 |
+
</div>
|
| 45 |
+
</footer>
|
| 46 |
+
`;
|
| 47 |
+
}
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
customElements.define('custom-footer', CustomFooter);
|
components/navbar.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
class CustomNavbar extends HTMLElement {
|
| 2 |
+
connectedCallback() {
|
| 3 |
+
this.attachShadow({ mode: 'open' });
|
| 4 |
+
this.shadowRoot.innerHTML = `
|
| 5 |
+
<style>
|
| 6 |
+
nav {
|
| 7 |
+
background: linear-gradient(135deg, #000000 0%, #1a1a1a 100%);
|
| 8 |
+
padding: 1rem 2rem;
|
| 9 |
+
display: flex;
|
| 10 |
+
justify-content: space-between;
|
| 11 |
+
align-items: center;
|
| 12 |
+
border-bottom: 2px solid #dc2626;
|
| 13 |
+
box-shadow: 0 4px 6px -1px rgba(220, 38, 38, 0.1);
|
| 14 |
+
}
|
| 15 |
+
.logo {
|
| 16 |
+
color: white;
|
| 17 |
+
font-weight: bold;
|
| 18 |
+
font-size: 1.5rem;
|
| 19 |
+
background: linear-gradient(45deg, #ffffff, #dc2626);
|
| 20 |
+
background-clip: text;
|
| 21 |
+
-webkit-background-clip: text;
|
| 22 |
+
-webkit-text-fill-color: transparent;
|
| 23 |
+
}
|
| 24 |
+
ul {
|
| 25 |
+
display: flex;
|
| 26 |
+
gap: 2rem;
|
| 27 |
+
list-style: none;
|
| 28 |
+
margin: 0;
|
| 29 |
+
padding: 0;
|
| 30 |
+
}
|
| 31 |
+
a {
|
| 32 |
+
color: #e5e5e5;
|
| 33 |
+
text-decoration: none;
|
| 34 |
+
transition: all 0.3s ease;
|
| 35 |
+
font-weight: 500;
|
| 36 |
+
}
|
| 37 |
+
a:hover {
|
| 38 |
+
color: #dc2626;
|
| 39 |
+
transform: translateY(-1px);
|
| 40 |
+
}
|
| 41 |
+
.nav-link {
|
| 42 |
+
position: relative;
|
| 43 |
+
}
|
| 44 |
+
.nav-link::after {
|
| 45 |
+
content: '';
|
| 46 |
+
position: absolute;
|
| 47 |
+
width: 0;
|
| 48 |
+
height: 2px;
|
| 49 |
+
bottom: -4px;
|
| 50 |
+
left: 0;
|
| 51 |
+
background: #dc2626;
|
| 52 |
+
transition: width 0.3s ease;
|
| 53 |
+
}
|
| 54 |
+
.nav-link:hover::after {
|
| 55 |
+
width: 100%;
|
| 56 |
+
}
|
| 57 |
+
@media (max-width: 768px) {
|
| 58 |
+
nav {
|
| 59 |
+
flex-direction: column;
|
| 60 |
+
gap: 1rem;
|
| 61 |
+
padding: 1rem;
|
| 62 |
+
}
|
| 63 |
+
ul {
|
| 64 |
+
gap: 1rem;
|
| 65 |
+
}
|
| 66 |
+
}
|
| 67 |
+
</style>
|
| 68 |
+
<nav>
|
| 69 |
+
<div class="logo">汉字猎人</div>
|
| 70 |
+
<ul>
|
| 71 |
+
<li><a href="/" class="nav-link">Home</a></li>
|
| 72 |
+
<li><a href="/about.html" class="nav-link">About</a></li>
|
| 73 |
+
<li><a href="/contact.html" class="nav-link">Contact</a></li>
|
| 74 |
+
</ul>
|
| 75 |
+
</nav>
|
| 76 |
+
`;
|
| 77 |
+
}
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
customElements.define('custom-navbar', CustomNavbar);
|
index.html
CHANGED
|
@@ -1,19 +1,160 @@
|
|
| 1 |
-
<!
|
| 2 |
-
<html>
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en" class="dark">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>Hanzi Hunter - Chinese Vocabulary Level Checker</title>
|
| 7 |
+
<link rel="stylesheet" href="style.css">
|
| 8 |
+
<script src="https://cdn.tailwindcss.com"></script>
|
| 9 |
+
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
|
| 10 |
+
<script src="https://unpkg.com/feather-icons"></script>
|
| 11 |
+
<script>
|
| 12 |
+
tailwind.config = {
|
| 13 |
+
darkMode: 'class',
|
| 14 |
+
theme: {
|
| 15 |
+
extend: {
|
| 16 |
+
colors: {
|
| 17 |
+
primary: '#000000',
|
| 18 |
+
secondary: '#DC2626'
|
| 19 |
+
}
|
| 20 |
+
}
|
| 21 |
+
}
|
| 22 |
+
}
|
| 23 |
+
</script>
|
| 24 |
+
</head>
|
| 25 |
+
<body class="bg-black text-white min-h-screen flex flex-col">
|
| 26 |
+
<custom-navbar></custom-navbar>
|
| 27 |
+
|
| 28 |
+
<main class="flex-1 container mx-auto px-4 py-8">
|
| 29 |
+
<!-- Hero Section -->
|
| 30 |
+
<section class="text-center mb-12">
|
| 31 |
+
<h1 class="text-4xl md:text-6xl font-bold mb-4 bg-gradient-to-r from-white to-red-600 bg-clip-text text-transparent">
|
| 32 |
+
汉字猎人
|
| 33 |
+
</h1>
|
| 34 |
+
<p class="text-xl text-gray-400 mb-8">Discover the secrets behind Chinese characters</p>
|
| 35 |
+
</section>
|
| 36 |
+
|
| 37 |
+
<!-- Main Input Section -->
|
| 38 |
+
<section class="max-w-2xl mx-auto mb-12">
|
| 39 |
+
<div class="bg-gray-900 rounded-2xl p-8 shadow-2xl border border-red-900">
|
| 40 |
+
<div class="flex items-center justify-center mb-6">
|
| 41 |
+
<i data-feather="search" class="w-6 h-6 text-red-500 mr-3"></i>
|
| 42 |
+
<h2 class="text-2xl font-bold">Check Your Chinese Vocabulary</h2>
|
| 43 |
+
</div>
|
| 44 |
+
|
| 45 |
+
<form id="wordForm" class="space-y-6">
|
| 46 |
+
<div>
|
| 47 |
+
<label for="chineseWord" class="block text-sm font-medium text-gray-300 mb-2">
|
| 48 |
+
Enter a Chinese Word
|
| 49 |
+
</label>
|
| 50 |
+
<input
|
| 51 |
+
type="text"
|
| 52 |
+
id="chineseWord"
|
| 53 |
+
placeholder="例如: 冒险, 你好, 学习..."
|
| 54 |
+
class="w-full px-4 py-3 bg-gray-800 border border-red-900 rounded-lg text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-red-500 focus:border-transparent transition-all duration-200"
|
| 55 |
+
required
|
| 56 |
+
>
|
| 57 |
+
</div>
|
| 58 |
+
|
| 59 |
+
<button
|
| 60 |
+
type="submit"
|
| 61 |
+
class="w-full bg-red-600 hover:bg-red-700 text-white font-bold py-3 px-4 rounded-lg transition-all duration-200 transform hover:scale-105 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-opacity-50"
|
| 62 |
+
>
|
| 63 |
+
<div class="flex items-center justify-center">
|
| 64 |
+
<i data-feather="zap" class="w-5 h-5 mr-2"></i>
|
| 65 |
+
Analyze Word
|
| 66 |
+
</div>
|
| 67 |
+
</button>
|
| 68 |
+
</form>
|
| 69 |
+
</div>
|
| 70 |
+
</section>
|
| 71 |
+
|
| 72 |
+
<!-- Results Section -->
|
| 73 |
+
<section id="resultsSection" class="max-w-2xl mx-auto hidden">
|
| 74 |
+
<div class="bg-gray-900 rounded-2xl p-8 shadow-2xl border border-red-900">
|
| 75 |
+
<div class="flex items-center justify-between mb-6">
|
| 76 |
+
<h3 class="text-2xl font-bold">Analysis Results</h3>
|
| 77 |
+
<button id="clearResults" class="text-red-400 hover:text-red-300 transition-colors">
|
| 78 |
+
<i data-feather="x" class="w-5 h-5"></i>
|
| 79 |
+
</button>
|
| 80 |
+
</div>
|
| 81 |
+
|
| 82 |
+
<div id="results" class="space-y-4">
|
| 83 |
+
<!-- Results will be populated here by JavaScript -->
|
| 84 |
+
</div>
|
| 85 |
+
</div>
|
| 86 |
+
</section>
|
| 87 |
+
<!-- API Configuration Section -->
|
| 88 |
+
<section class="max-w-2xl mx-auto mt-16">
|
| 89 |
+
<div class="bg-gray-900 rounded-2xl p-8 shadow-2xl border border-red-900">
|
| 90 |
+
<div class="flex items-center justify-center mb-6">
|
| 91 |
+
<i data-feather="settings" class="w-6 h-6 text-red-500 mr-3"></i>
|
| 92 |
+
<h2 class="text-2xl font-bold">API Configuration</h2>
|
| 93 |
+
</div>
|
| 94 |
+
|
| 95 |
+
<div class="space-y-4">
|
| 96 |
+
<div class="bg-gray-800 rounded-lg p-4">
|
| 97 |
+
<h3 class="text-lg font-semibold mb-2">How to Configure APIs</h3>
|
| 98 |
+
<p class="text-gray-400 mb-4">
|
| 99 |
+
To connect real APIs, update the configuration in <code class="bg-gray-700 px-2 py-1 rounded">api-config.js</code>
|
| 100 |
+
</p>
|
| 101 |
+
<div class="text-sm text-gray-500 space-y-2">
|
| 102 |
+
<p>1. Open <code class="bg-gray-700 px-2 py-1 rounded">api-config.js</code> file</p>
|
| 103 |
+
<p>2. Replace the placeholder URLs with your actual API endpoints</p>
|
| 104 |
+
<p>3. Add any required API keys or authentication headers</p>
|
| 105 |
+
</div>
|
| 106 |
+
</div>
|
| 107 |
+
|
| 108 |
+
<div class="mt-6 p-4 bg-yellow-900 border border-yellow-700 rounded-lg">
|
| 109 |
+
<div class="flex items-start">
|
| 110 |
+
<i data-feather="alert-triangle" class="w-5 h-5 text-yellow-400 mr-3 mt-1"></i>
|
| 111 |
+
<div>
|
| 112 |
+
<h4 class="font-semibold text-yellow-300">API Setup Required</h4>
|
| 113 |
+
<p class="text-yellow-200 text-sm">Currently using demo data. Connect real APIs for live data.</p>
|
| 114 |
+
</div>
|
| 115 |
+
</div>
|
| 116 |
+
</div>
|
| 117 |
+
</div>
|
| 118 |
+
</div>
|
| 119 |
+
</section>
|
| 120 |
+
|
| 121 |
+
<!-- Features Section -->
|
| 122 |
+
<section class="max-w-4xl mx-auto mt-16">
|
| 123 |
+
<h2 class="text-3xl font-bold text-center mb-12">Why Use Hanzi Hunter?</h2>
|
| 124 |
+
<div class="grid md:grid-cols-3 gap-8">
|
| 125 |
+
<div class="text-center p-6 bg-gray-900 rounded-xl border border-red-900">
|
| 126 |
+
<i data-feather="award" class="w-12 h-12 text-red-500 mx-auto mb-4"></i>
|
| 127 |
+
<h3 class="text-xl font-bold mb-2">HSK Level Detection</h3>
|
| 128 |
+
<p class="text-gray-400">Instantly identify which HSK level your word belongs to</p>
|
| 129 |
+
</div>
|
| 130 |
+
<div class="text-center p-6 bg-gray-900 rounded-xl border border-red-900">
|
| 131 |
+
<i data-feather="message-circle" class="w-12 h-12 text-red-500 mx-auto mb-4"></i>
|
| 132 |
+
<h3 class="text-xl font-bold mb-2">Usage Analysis</h3>
|
| 133 |
+
<p class="text-gray-400">Learn whether words are formal, informal, common or rare</p>
|
| 134 |
+
</div>
|
| 135 |
+
<div class="text-center p-6 bg-gray-900 rounded-xl border border-red-900">
|
| 136 |
+
<i data-feather="book-open" class="w-12 h-12 text-red-500 mx-auto mb-4"></i>
|
| 137 |
+
<h3 class="text-xl font-bold mb-2">Quick Meanings</h3>
|
| 138 |
+
<p class="text-gray-400">Get concise English definitions for better understanding</p>
|
| 139 |
+
</div>
|
| 140 |
+
</div>
|
| 141 |
+
</section>
|
| 142 |
+
</main>
|
| 143 |
+
|
| 144 |
+
<custom-footer></custom-footer>
|
| 145 |
+
<!-- API Configuration -->
|
| 146 |
+
<script src="api-config.js"></script>
|
| 147 |
+
|
| 148 |
+
<!-- Component Scripts -->
|
| 149 |
+
<script src="components/navbar.js"></script>
|
| 150 |
+
<script src="components/footer.js"></script>
|
| 151 |
+
|
| 152 |
+
<!-- Main Script -->
|
| 153 |
+
<script src="script.js"></script>
|
| 154 |
+
<!-- Feather Icons -->
|
| 155 |
+
<script>
|
| 156 |
+
feather.replace();
|
| 157 |
+
</script>
|
| 158 |
+
<script src="https://huggingface.co/deepsite/deepsite-badge.js"></script>
|
| 159 |
+
</body>
|
| 160 |
+
</html>
|
script.js
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
// Shared JavaScript across all pages
|
| 3 |
+
|
| 4 |
+
// HSK word database (simplified version - fallback)
|
| 5 |
+
const hskDatabase = {
|
| 6 |
+
"你好": { level: 1, style: "Neutral", usage: "Common", meaning: "hello" },
|
| 7 |
+
"学习": { level: 1, style: "Neutral", usage: "Common", meaning: "study, learn" },
|
| 8 |
+
"谢谢": { level: 1, style: "Neutral", usage: "Common", meaning: "thank you" },
|
| 9 |
+
"再见": { level: 1, style: "Neutral", usage: "Common", meaning: "goodbye" },
|
| 10 |
+
"是": { level: 1, style: "Neutral", usage: "Common", meaning: "to be" },
|
| 11 |
+
"不": { level: 1, style: "Neutral", usage: "Common", meaning: "no, not" },
|
| 12 |
+
"我": { level: 1, style: "Neutral", usage: "Common", meaning: "I, me" },
|
| 13 |
+
"你": { level: 1, style: "Neutral", usage: "Common", meaning: "you" },
|
| 14 |
+
"好": { level: 1, style: "Neutral", usage: "Common", meaning: "good" },
|
| 15 |
+
"人": { level: 1, style: "Neutral", usage: "Common", meaning: "person" },
|
| 16 |
+
"冒险": { level: 4, style: "Neutral", usage: "Common", meaning: "adventure, take risks" },
|
| 17 |
+
"尴尬": { level: 5, style: "Neutral", usage: "Common", meaning: "embarrassed, awkward" },
|
| 18 |
+
"牛逼": { level: "Not in HSK", style: "Informal", usage: "Common", meaning: "awesome, amazing" },
|
| 19 |
+
"囧": { level: "Not in HSK", style: "Informal", usage: "Rare", meaning: "embarrassed, awkward" },
|
| 20 |
+
"饕餮": { level: "Not in HSK", style: "Formal", usage: "Rare", meaning: "gluttonous monster" },
|
| 21 |
+
"耄耋": { level: "Not in HSK", style: "Formal", usage: "Rare", meaning: "very old age" }
|
| 22 |
+
};
|
| 23 |
+
// DOM Elements
|
| 24 |
+
const wordForm = document.getElementById('wordForm');
|
| 25 |
+
const chineseWordInput = document.getElementById('chineseWord');
|
| 26 |
+
const resultsSection = document.getElementById('resultsSection');
|
| 27 |
+
const resultsDiv = document.getElementById('results');
|
| 28 |
+
const clearResultsBtn = document.getElementById('clearResults');
|
| 29 |
+
|
| 30 |
+
// Initialize the application
|
| 31 |
+
document.addEventListener('DOMContentLoaded', function() {
|
| 32 |
+
console.log('Hanzi Hunter initialized');
|
| 33 |
+
|
| 34 |
+
// Form submission handler
|
| 35 |
+
wordForm.addEventListener('submit', function(e) {
|
| 36 |
+
e.preventDefault();
|
| 37 |
+
const word = chineseWordInput.value.trim();
|
| 38 |
+
|
| 39 |
+
if (word) {
|
| 40 |
+
analyzeWord(word);
|
| 41 |
+
}
|
| 42 |
+
});
|
| 43 |
+
|
| 44 |
+
// Clear results handler
|
| 45 |
+
clearResultsBtn.addEventListener('click', function() {
|
| 46 |
+
clearResults();
|
| 47 |
+
});
|
| 48 |
+
|
| 49 |
+
// Load any saved results from localStorage
|
| 50 |
+
loadSavedResults();
|
| 51 |
+
});
|
| 52 |
+
// Analyze the Chinese word
|
| 53 |
+
async function analyzeWord(word) {
|
| 54 |
+
// Check if input is Chinese characters
|
| 55 |
+
if (!isChinese(word)) {
|
| 56 |
+
showError("Please enter a valid Chinese word.");
|
| 57 |
+
return;
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
try {
|
| 61 |
+
// Try to fetch from API first
|
| 62 |
+
const wordData = await fetchWordData(word);
|
| 63 |
+
displayResults(word, wordData);
|
| 64 |
+
saveResults(word, wordData);
|
| 65 |
+
} catch (error) {
|
| 66 |
+
console.error('API Error:', error);
|
| 67 |
+
// Fallback to local database
|
| 68 |
+
const localData = hskDatabase[word] || {
|
| 69 |
+
level: "Not in HSK",
|
| 70 |
+
style: "Neutral",
|
| 71 |
+
usage: "Rare",
|
| 72 |
+
meaning: "unknown meaning"
|
| 73 |
+
};
|
| 74 |
+
displayResults(word, localData);
|
| 75 |
+
saveResults(word, localData);
|
| 76 |
+
}
|
| 77 |
+
}
|
| 78 |
+
|
| 79 |
+
// Fetch word data from APIs
|
| 80 |
+
async function fetchWordData(word) {
|
| 81 |
+
// You can implement multiple API calls here
|
| 82 |
+
// Example using dictionary API
|
| 83 |
+
try {
|
| 84 |
+
const response = await fetch(`${apiConfig.getAPI('dictionary').url}${encodeURIComponent(word)}`);
|
| 85 |
+
|
| 86 |
+
if (response.ok) {
|
| 87 |
+
const data = await response.json();
|
| 88 |
+
return processAPIData(data, word);
|
| 89 |
+
}
|
| 90 |
+
} catch (error) {
|
| 91 |
+
console.error('Dictionary API failed:', error);
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
// If no API works, throw error to trigger fallback
|
| 95 |
+
throw new Error('All APIs failed');
|
| 96 |
+
}
|
| 97 |
+
|
| 98 |
+
// Process API response data
|
| 99 |
+
function processAPIData(apiData, word) {
|
| 100 |
+
// Process the API response and extract relevant information
|
| 101 |
+
// This is a placeholder - adjust based on your API response structure
|
| 102 |
+
return {
|
| 103 |
+
level: "Checking...",
|
| 104 |
+
style: "Neutral",
|
| 105 |
+
usage: "Common",
|
| 106 |
+
meaning: apiData[0]?.meanings?.[0]?.definitions?.[0]?.definition || "Meaning not found",
|
| 107 |
+
source: "API"
|
| 108 |
+
};
|
| 109 |
+
}
|
| 110 |
+
// Check if string contains Chinese characters
|
| 111 |
+
function isChinese(str) {
|
| 112 |
+
return /[\u4e00-\u9fff]/.test(str);
|
| 113 |
+
}
|
| 114 |
+
|
| 115 |
+
// Display analysis results
|
| 116 |
+
function displayResults(word, data) {
|
| 117 |
+
resultsSection.classList.remove('hidden');
|
| 118 |
+
resultsSection.classList.add('fade-in-up');
|
| 119 |
+
|
| 120 |
+
let warningText = '';
|
| 121 |
+
if (data.style === "Informal") {
|
| 122 |
+
warningText = '<p class="text-yellow-400 text-sm mt-2"><i data-feather="alert-triangle" class="w-4 h-4 inline mr-1"></i>This is casual spoken Chinese.</p>';
|
| 123 |
+
} else if (data.style === "Formal" || data.usage === "Rare") {
|
| 124 |
+
warningText = '<p class="text-orange-400 text-sm mt-2"><i data-feather="info" class="w-4 h-4 inline mr-1"></i>This word is mostly used in formal writing.</p>';
|
| 125 |
+
}
|
| 126 |
+
|
| 127 |
+
resultsDiv.innerHTML = `
|
| 128 |
+
<div class="bg-gray-800 rounded-lg p-4 border-l-4 border-red-500">
|
| 129 |
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
| 130 |
+
<div>
|
| 131 |
+
<p class="text-gray-400 text-sm">Word</p>
|
| 132 |
+
<p class="text-2xl font-bold">${word}</p>
|
| 133 |
+
</div>
|
| 134 |
+
<div>
|
| 135 |
+
<p class="text-gray-400 text-sm">HSK Level</p>
|
| 136 |
+
<p class="text-xl font-semibold">${data.level}</p>
|
| 137 |
+
</div>
|
| 138 |
+
<div>
|
| 139 |
+
<p class="text-gray-400 text-sm">Style</p>
|
| 140 |
+
<p class="text-xl font-semibold">${data.style}</p>
|
| 141 |
+
</div>
|
| 142 |
+
<div>
|
| 143 |
+
<p class="text-gray-400 text-sm">Usage</p>
|
| 144 |
+
<p class="text-xl font-semibold">${data.usage}</p>
|
| 145 |
+
</div>
|
| 146 |
+
<div>
|
| 147 |
+
<p class="text-gray-400 text-sm">Meaning</p>
|
| 148 |
+
<p class="text-xl font-semibold">${data.meaning}</p>
|
| 149 |
+
</div>
|
| 150 |
+
</div>
|
| 151 |
+
${warningText}
|
| 152 |
+
</div>
|
| 153 |
+
`;
|
| 154 |
+
|
| 155 |
+
// Update feather icons in the new content
|
| 156 |
+
feather.replace();
|
| 157 |
+
|
| 158 |
+
// Scroll to results
|
| 159 |
+
resultsSection.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
| 160 |
+
}
|
| 161 |
+
|
| 162 |
+
// Show error message
|
| 163 |
+
function showError(message) {
|
| 164 |
+
resultsSection.classList.remove('hidden');
|
| 165 |
+
resultsDiv.innerHTML = `
|
| 166 |
+
<div class="bg-red-900 rounded-lg p-4 border-l-4 border-red-500">
|
| 167 |
+
<div class="flex items-center">
|
| 168 |
+
<i data-feather="alert-circle" class="w-6 h-6 text-red-300 mr-3"></i>
|
| 169 |
+
<p class="text-red-300">${message}</p>
|
| 170 |
+
</div>
|
| 171 |
+
</div>
|
| 172 |
+
`;
|
| 173 |
+
feather.replace();
|
| 174 |
+
}
|
| 175 |
+
|
| 176 |
+
// Clear results
|
| 177 |
+
function clearResults() {
|
| 178 |
+
resultsSection.classList.add('hidden');
|
| 179 |
+
chineseWordInput.value = '';
|
| 180 |
+
chineseWordInput.focus();
|
| 181 |
+
localStorage.removeItem('lastWordAnalysis');
|
| 182 |
+
}
|
| 183 |
+
|
| 184 |
+
// Save results to localStorage
|
| 185 |
+
function saveResults(word, data) {
|
| 186 |
+
const analysis = {
|
| 187 |
+
word: word,
|
| 188 |
+
data: data,
|
| 189 |
+
timestamp: new Date().toISOString()
|
| 190 |
+
};
|
| 191 |
+
localStorage.setItem('lastWordAnalysis', JSON.stringify(analysis));
|
| 192 |
+
}
|
| 193 |
+
|
| 194 |
+
// Load saved results from localStorage
|
| 195 |
+
function loadSavedResults() {
|
| 196 |
+
const saved = localStorage.getItem('lastWordAnalysis');
|
| 197 |
+
if (saved) {
|
| 198 |
+
const analysis = JSON.parse(saved);
|
| 199 |
+
displayResults(analysis.word, analysis.data);
|
| 200 |
+
}
|
| 201 |
+
}
|
| 202 |
+
|
| 203 |
+
// Theme management (for future use)
|
| 204 |
+
function toggleTheme() {
|
| 205 |
+
document.documentElement.classList.toggle('dark');
|
| 206 |
+
}
|
style.css
CHANGED
|
@@ -1,28 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
| 1 |
body {
|
| 2 |
-
|
| 3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
}
|
| 5 |
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
margin-top: 0;
|
| 9 |
}
|
| 10 |
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
margin-bottom: 10px;
|
| 15 |
-
margin-top: 5px;
|
| 16 |
}
|
| 17 |
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
}
|
| 25 |
|
| 26 |
-
.
|
| 27 |
-
|
| 28 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* Shared styles across all pages */
|
| 2 |
+
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
|
| 3 |
+
|
| 4 |
body {
|
| 5 |
+
font-family: 'Inter', sans-serif;
|
| 6 |
+
}
|
| 7 |
+
|
| 8 |
+
/* Custom scrollbar */
|
| 9 |
+
::-webkit-scrollbar {
|
| 10 |
+
width: 8px;
|
| 11 |
+
}
|
| 12 |
+
|
| 13 |
+
::-webkit-scrollbar-track {
|
| 14 |
+
background: #1a1a1a;
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
::-webkit-scrollbar-thumb {
|
| 18 |
+
background: #dc2626;
|
| 19 |
+
border-radius: 4px;
|
| 20 |
}
|
| 21 |
|
| 22 |
+
::-webkit-scrollbar-thumb:hover {
|
| 23 |
+
background: #b91c1c;
|
|
|
|
| 24 |
}
|
| 25 |
|
| 26 |
+
/* Smooth transitions for theme switching */
|
| 27 |
+
* {
|
| 28 |
+
transition: background-color 0.2s ease, border-color 0.2s ease;
|
|
|
|
|
|
|
| 29 |
}
|
| 30 |
|
| 31 |
+
/* Custom animations */
|
| 32 |
+
@keyframes fadeInUp {
|
| 33 |
+
from {
|
| 34 |
+
opacity: 0;
|
| 35 |
+
transform: translateY(20px);
|
| 36 |
+
}
|
| 37 |
+
to {
|
| 38 |
+
opacity: 1;
|
| 39 |
+
transform: translateY(0);
|
| 40 |
+
}
|
| 41 |
}
|
| 42 |
|
| 43 |
+
.fade-in-up {
|
| 44 |
+
animation: fadeInUp 0.5s ease-out;
|
| 45 |
}
|
| 46 |
+
|
| 47 |
+
/* Focus styles for accessibility */
|
| 48 |
+
input:focus, button:focus {
|
| 49 |
+
outline: 2px solid #dc2626;
|
| 50 |
+
outline-offset: 2px;
|
| 51 |
+
}
|