Spaces:
Running
Running
Upload 38 files
#352
by
aakash1777
- opened
- booknap project/.vscode/launch.json +30 -0
- booknap project/DATASET_GUIDE.md +327 -0
- booknap project/README.md +134 -0
- booknap project/animated-tabs.css +441 -0
- booknap project/animated-tabs.html +658 -0
- booknap project/animated-tabs.js +143 -0
- booknap project/app.py +237 -0
- booknap project/assets/audio/7-habits-summary.mp3 +1 -0
- booknap project/assets/audio/atomic-habits-summary.mp3 +1 -0
- booknap project/assets/audio/rich-dad-poor-dad-summary.mp3 +1 -0
- booknap project/assets/audio/thinking-fast-slow-summary.mp3 +1 -0
- booknap project/assets/covers/7-habits.jpg +48 -0
- booknap project/assets/covers/7-habits.svg +48 -0
- booknap project/assets/covers/atomic-habits.jpg +36 -0
- booknap project/assets/covers/atomic-habits.svg +36 -0
- booknap project/assets/covers/jane-austen-portrait.svg +77 -0
- booknap project/assets/covers/rich-dad-poor-dad.jpg +40 -0
- booknap project/assets/covers/rich-dad-poor-dad.svg +40 -0
- booknap project/assets/covers/start-with-why.svg +51 -0
- booknap project/assets/covers/thinking-fast-slow.jpg +38 -0
- booknap project/assets/covers/thinking-fast-slow.svg +38 -0
- booknap project/assets/covers/zero-to-one.svg +49 -0
- booknap project/blog.html +612 -0
- booknap project/books.html +1072 -0
- booknap project/business-leaders.html +376 -0
- booknap project/community-section.html +285 -0
- booknap project/data/news.json +86 -0
- booknap project/database_schema.sql +21 -0
- booknap project/json-blog.html +272 -0
- booknap project/login.html +120 -0
- booknap project/pricing.html +521 -0
- booknap project/requirements.txt +8 -0
- booknap project/script.js +1 -0
- booknap project/setup_database.py +102 -0
- booknap project/signup.html +371 -0
- booknap project/static-blog.html +222 -0
- booknap project/styles.css +973 -0
- booknap project/test_connection.py +49 -0
booknap project/.vscode/launch.json
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
// Use IntelliSense to learn about possible attributes.
|
3 |
+
// Hover to view descriptions of existing attributes.
|
4 |
+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
5 |
+
"version": "0.2.0",
|
6 |
+
"configurations": [
|
7 |
+
{
|
8 |
+
"name": "Launch Edge",
|
9 |
+
"request": "launch",
|
10 |
+
"type": "msedge",
|
11 |
+
"url": "http://localhost:8080",
|
12 |
+
"webRoot": "${workspaceFolder}"
|
13 |
+
},
|
14 |
+
{
|
15 |
+
"type": "vscode-edge-devtools.debug",
|
16 |
+
"request": "attach",
|
17 |
+
"name": "Attach to Microsoft Edge and open the Edge DevTools",
|
18 |
+
"url": "http://localhost:8080",
|
19 |
+
"webRoot": "${workspaceFolder}"
|
20 |
+
},
|
21 |
+
|
22 |
+
|
23 |
+
{
|
24 |
+
"type": "chrome",
|
25 |
+
"request": "launch",
|
26 |
+
"name": "Open book.html",
|
27 |
+
"file": "/home/aakash/Documents/booknap project/book.html"
|
28 |
+
}
|
29 |
+
]
|
30 |
+
}
|
booknap project/DATASET_GUIDE.md
ADDED
@@ -0,0 +1,327 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# How to Use Datasets in Web Pages - Complete Guide
|
2 |
+
|
3 |
+
## π― **Overview**
|
4 |
+
|
5 |
+
There are several ways to integrate datasets into web pages, each with different use cases and complexity levels.
|
6 |
+
|
7 |
+
## π **Method 1: Static Data (Simplest)**
|
8 |
+
|
9 |
+
**Best for:** Small datasets, static content, simple applications
|
10 |
+
|
11 |
+
### How it works:
|
12 |
+
- Data is embedded directly in JavaScript
|
13 |
+
- No server required
|
14 |
+
- Works with static hosting (GitHub Pages, Netlify, etc.)
|
15 |
+
|
16 |
+
### Example:
|
17 |
+
```javascript
|
18 |
+
const dataset = [
|
19 |
+
{ title: "Article 1", content: "..." },
|
20 |
+
{ title: "Article 2", content: "..." }
|
21 |
+
];
|
22 |
+
```
|
23 |
+
|
24 |
+
### Files created:
|
25 |
+
- `static-blog.html` - Complete example with embedded dataset
|
26 |
+
|
27 |
+
### Pros:
|
28 |
+
- β
No server needed
|
29 |
+
- β
Fast loading
|
30 |
+
- β
Simple to implement
|
31 |
+
- β
Works offline
|
32 |
+
|
33 |
+
### Cons:
|
34 |
+
- β Limited to small datasets
|
35 |
+
- β Data can't be updated without code changes
|
36 |
+
- β No real-time updates
|
37 |
+
|
38 |
+
---
|
39 |
+
|
40 |
+
## π **Method 2: External JSON Files**
|
41 |
+
|
42 |
+
**Best for:** Medium datasets, content that updates occasionally
|
43 |
+
|
44 |
+
### How it works:
|
45 |
+
- Data stored in separate JSON files
|
46 |
+
- Loaded via `fetch()` API
|
47 |
+
- Can be updated without changing code
|
48 |
+
|
49 |
+
### Example:
|
50 |
+
```javascript
|
51 |
+
async function loadData() {
|
52 |
+
const response = await fetch('data/dataset.json');
|
53 |
+
const data = await response.json();
|
54 |
+
displayData(data);
|
55 |
+
}
|
56 |
+
```
|
57 |
+
|
58 |
+
### Files created:
|
59 |
+
- `data/news.json` - Sample dataset
|
60 |
+
- `json-blog.html` - Complete example with JSON loading
|
61 |
+
|
62 |
+
### Pros:
|
63 |
+
- β
Separates data from code
|
64 |
+
- β
Easy to update content
|
65 |
+
- β
No server required
|
66 |
+
- β
Good for static sites
|
67 |
+
|
68 |
+
### Cons:
|
69 |
+
- β Limited by browser CORS policies
|
70 |
+
- β No real-time updates
|
71 |
+
- β File size limitations
|
72 |
+
|
73 |
+
---
|
74 |
+
|
75 |
+
## π₯οΈ **Method 3: Backend API (Advanced)**
|
76 |
+
|
77 |
+
**Best for:** Large datasets, real-time updates, complex applications
|
78 |
+
|
79 |
+
### How it works:
|
80 |
+
- Python/Node.js server processes data
|
81 |
+
- REST API endpoints serve data
|
82 |
+
- Can integrate with databases
|
83 |
+
|
84 |
+
### Example:
|
85 |
+
```python
|
86 |
+
from flask import Flask, jsonify
|
87 |
+
import pandas as pd
|
88 |
+
|
89 |
+
app = Flask(__name__)
|
90 |
+
|
91 |
+
@app.route('/api/data')
|
92 |
+
def get_data():
|
93 |
+
df = pd.read_csv('dataset.csv')
|
94 |
+
return jsonify(df.to_dict('records'))
|
95 |
+
```
|
96 |
+
|
97 |
+
### Files created:
|
98 |
+
- `app.py` - Flask backend with Kaggle dataset
|
99 |
+
- `requirements.txt` - Python dependencies
|
100 |
+
|
101 |
+
### Pros:
|
102 |
+
- β
Handle large datasets
|
103 |
+
- β
Real-time updates
|
104 |
+
- β
Database integration
|
105 |
+
- β
Data processing capabilities
|
106 |
+
|
107 |
+
### Cons:
|
108 |
+
- β Requires server setup
|
109 |
+
- β More complex
|
110 |
+
- β Hosting costs
|
111 |
+
|
112 |
+
---
|
113 |
+
|
114 |
+
## π§ **Method 4: Database Integration**
|
115 |
+
|
116 |
+
**Best for:** Production applications, user-generated content
|
117 |
+
|
118 |
+
### Options:
|
119 |
+
1. **SQLite** - Lightweight, file-based
|
120 |
+
2. **PostgreSQL** - Full-featured, scalable
|
121 |
+
3. **MongoDB** - NoSQL, flexible
|
122 |
+
4. **Firebase** - Cloud-hosted, real-time
|
123 |
+
|
124 |
+
### Example with SQLite:
|
125 |
+
```python
|
126 |
+
import sqlite3
|
127 |
+
|
128 |
+
def get_articles():
|
129 |
+
conn = sqlite3.connect('blog.db')
|
130 |
+
cursor = conn.cursor()
|
131 |
+
cursor.execute('SELECT * FROM articles')
|
132 |
+
return cursor.fetchall()
|
133 |
+
```
|
134 |
+
|
135 |
+
---
|
136 |
+
|
137 |
+
## π **Quick Start Guide**
|
138 |
+
|
139 |
+
### For Beginners (Static Data):
|
140 |
+
1. Open `static-blog.html`
|
141 |
+
2. Replace the `newsDataset` array with your data
|
142 |
+
3. Open in browser - that's it!
|
143 |
+
|
144 |
+
### For Intermediate (JSON Files):
|
145 |
+
1. Create your data in `data/your-data.json`
|
146 |
+
2. Open `json-blog.html`
|
147 |
+
3. Update the fetch path to your JSON file
|
148 |
+
4. Open in browser
|
149 |
+
|
150 |
+
### For Advanced (Backend):
|
151 |
+
1. Install Python dependencies: `pip install -r requirements.txt`
|
152 |
+
2. Set up Kaggle API (if using Kaggle datasets)
|
153 |
+
3. Run: `python app.py`
|
154 |
+
4. Open `http://localhost:5000`
|
155 |
+
|
156 |
+
---
|
157 |
+
|
158 |
+
## π **Dataset Formats**
|
159 |
+
|
160 |
+
### JSON (Recommended):
|
161 |
+
```json
|
162 |
+
{
|
163 |
+
"articles": [
|
164 |
+
{
|
165 |
+
"title": "Article Title",
|
166 |
+
"content": "Article content...",
|
167 |
+
"date": "2024-01-15",
|
168 |
+
"tags": ["tag1", "tag2"]
|
169 |
+
}
|
170 |
+
]
|
171 |
+
}
|
172 |
+
```
|
173 |
+
|
174 |
+
### CSV:
|
175 |
+
```csv
|
176 |
+
title,content,date,tags
|
177 |
+
"Article 1","Content 1","2024-01-15","tag1,tag2"
|
178 |
+
"Article 2","Content 2","2024-01-16","tag3"
|
179 |
+
```
|
180 |
+
|
181 |
+
### Excel:
|
182 |
+
- Convert to CSV or JSON for web use
|
183 |
+
- Use Python pandas for processing
|
184 |
+
|
185 |
+
---
|
186 |
+
|
187 |
+
## π¨ **Integration Examples**
|
188 |
+
|
189 |
+
### Search Functionality:
|
190 |
+
```javascript
|
191 |
+
function searchData(query) {
|
192 |
+
return dataset.filter(item =>
|
193 |
+
item.title.toLowerCase().includes(query.toLowerCase())
|
194 |
+
);
|
195 |
+
}
|
196 |
+
```
|
197 |
+
|
198 |
+
### Filtering:
|
199 |
+
```javascript
|
200 |
+
function filterByCategory(category) {
|
201 |
+
return dataset.filter(item => item.category === category);
|
202 |
+
}
|
203 |
+
```
|
204 |
+
|
205 |
+
### Sorting:
|
206 |
+
```javascript
|
207 |
+
function sortByDate() {
|
208 |
+
return dataset.sort((a, b) => new Date(b.date) - new Date(a.date));
|
209 |
+
}
|
210 |
+
```
|
211 |
+
|
212 |
+
### Pagination:
|
213 |
+
```javascript
|
214 |
+
function getPage(page, itemsPerPage) {
|
215 |
+
const start = page * itemsPerPage;
|
216 |
+
return dataset.slice(start, start + itemsPerPage);
|
217 |
+
}
|
218 |
+
```
|
219 |
+
|
220 |
+
---
|
221 |
+
|
222 |
+
## π **Popular Dataset Sources**
|
223 |
+
|
224 |
+
### Free Datasets:
|
225 |
+
- **Kaggle** - `kagglehub.dataset_download("dataset-name")`
|
226 |
+
- **GitHub** - Raw JSON/CSV files
|
227 |
+
- **Open Data Portals** - Government data
|
228 |
+
- **APIs** - News APIs, weather APIs, etc.
|
229 |
+
|
230 |
+
### Creating Your Own:
|
231 |
+
1. **Google Sheets** οΏ½οΏ½ Export as CSV/JSON
|
232 |
+
2. **Excel** β Save as CSV
|
233 |
+
3. **Database** β Export queries
|
234 |
+
4. **Web Scraping** β Collect data programmatically
|
235 |
+
|
236 |
+
---
|
237 |
+
|
238 |
+
## π οΈ **Tools & Libraries**
|
239 |
+
|
240 |
+
### Frontend:
|
241 |
+
- **Vanilla JavaScript** - Built-in fetch API
|
242 |
+
- **Axios** - HTTP client
|
243 |
+
- **D3.js** - Data visualization
|
244 |
+
- **Chart.js** - Charts and graphs
|
245 |
+
|
246 |
+
### Backend:
|
247 |
+
- **Flask** - Python web framework
|
248 |
+
- **Express.js** - Node.js framework
|
249 |
+
- **Pandas** - Data processing
|
250 |
+
- **SQLAlchemy** - Database ORM
|
251 |
+
|
252 |
+
---
|
253 |
+
|
254 |
+
## π± **Mobile Considerations**
|
255 |
+
|
256 |
+
### Responsive Design:
|
257 |
+
```css
|
258 |
+
@media (max-width: 768px) {
|
259 |
+
.blog-grid {
|
260 |
+
grid-template-columns: 1fr;
|
261 |
+
}
|
262 |
+
}
|
263 |
+
```
|
264 |
+
|
265 |
+
### Performance:
|
266 |
+
- Lazy loading for large datasets
|
267 |
+
- Image optimization
|
268 |
+
- Data caching
|
269 |
+
- Progressive loading
|
270 |
+
|
271 |
+
---
|
272 |
+
|
273 |
+
## π **Security & Privacy**
|
274 |
+
|
275 |
+
### Best Practices:
|
276 |
+
- Validate all data inputs
|
277 |
+
- Sanitize data before display
|
278 |
+
- Use HTTPS for API calls
|
279 |
+
- Implement rate limiting
|
280 |
+
- Handle errors gracefully
|
281 |
+
|
282 |
+
### CORS Issues:
|
283 |
+
```python
|
284 |
+
# Flask CORS setup
|
285 |
+
from flask_cors import CORS
|
286 |
+
app = Flask(__name__)
|
287 |
+
CORS(app)
|
288 |
+
```
|
289 |
+
|
290 |
+
---
|
291 |
+
|
292 |
+
## π **Performance Tips**
|
293 |
+
|
294 |
+
1. **Compress data** - Use gzip compression
|
295 |
+
2. **Cache responses** - Store data locally
|
296 |
+
3. **Lazy load** - Load data as needed
|
297 |
+
4. **Pagination** - Load data in chunks
|
298 |
+
5. **CDN** - Use content delivery networks
|
299 |
+
|
300 |
+
---
|
301 |
+
|
302 |
+
## π― **Choose Your Method**
|
303 |
+
|
304 |
+
| Method | Dataset Size | Complexity | Real-time | Hosting |
|
305 |
+
|--------|-------------|------------|-----------|---------|
|
306 |
+
| Static | < 1MB | Low | No | Static |
|
307 |
+
| JSON | < 10MB | Low | No | Static |
|
308 |
+
| API | Any | Medium | Yes | Server |
|
309 |
+
| Database | Any | High | Yes | Server |
|
310 |
+
|
311 |
+
---
|
312 |
+
|
313 |
+
## π **Next Steps**
|
314 |
+
|
315 |
+
1. **Start with static data** if you're new to web development
|
316 |
+
2. **Move to JSON files** when you need more data
|
317 |
+
3. **Add a backend** when you need real-time updates
|
318 |
+
4. **Integrate a database** for production applications
|
319 |
+
|
320 |
+
Remember: Start simple and scale up as needed!
|
321 |
+
|
322 |
+
|
323 |
+
|
324 |
+
|
325 |
+
|
326 |
+
|
327 |
+
|
booknap project/README.md
ADDED
@@ -0,0 +1,134 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Booknap - Book Summary Platform
|
2 |
+
|
3 |
+
A modern web application for accessing book summaries, with user authentication and a beautiful UI.
|
4 |
+
|
5 |
+
## Features
|
6 |
+
|
7 |
+
- **User Authentication**: Login and signup functionality
|
8 |
+
- **Book Summaries**: Access to various book summaries and insights
|
9 |
+
- **Responsive Design**: Modern, mobile-friendly interface
|
10 |
+
- **Database Integration**: PostgreSQL backend with user management
|
11 |
+
- **Blog System**: Integrated blog with dynamic content
|
12 |
+
|
13 |
+
## Pages
|
14 |
+
|
15 |
+
- **Home** (`books.html`): Main landing page with book summaries
|
16 |
+
- **Login** (`login.html`): User authentication
|
17 |
+
- **Signup** (`signup.html`): User registration
|
18 |
+
- **Pricing** (`pricing.html`): Subscription plans
|
19 |
+
- **Blog** (`blog.html`): Blog articles and insights
|
20 |
+
|
21 |
+
## Setup Instructions
|
22 |
+
|
23 |
+
### 1. Install Dependencies
|
24 |
+
|
25 |
+
```bash
|
26 |
+
pip install -r requirements.txt
|
27 |
+
```
|
28 |
+
|
29 |
+
### 2. Database Setup
|
30 |
+
|
31 |
+
#### Option A: Using Python Scripts (Recommended)
|
32 |
+
1. Set your database password:
|
33 |
+
```bash
|
34 |
+
export DATABASE_URL="postgresql://postgres:YOUR_PASSWORD@db.ckrqyjfdifjbsuuofegd.supabase.co:5432/postgres"
|
35 |
+
```
|
36 |
+
2. Run the database setup script:
|
37 |
+
```bash
|
38 |
+
python setup_database.py
|
39 |
+
```
|
40 |
+
|
41 |
+
#### Option B: Using psql Command
|
42 |
+
1. Install PostgreSQL client: `sudo dnf install postgresql` (Fedora/RHEL)
|
43 |
+
2. Run the schema:
|
44 |
+
```bash
|
45 |
+
PGPASSWORD=YOUR_PASSWORD psql -h db.ckrqyjfdifjbsuuofegd.supabase.co -p 5432 -d postgres -U postgres -f database_schema.sql
|
46 |
+
```
|
47 |
+
|
48 |
+
**Note**: Replace `YOUR_PASSWORD` with your actual Supabase database password.
|
49 |
+
|
50 |
+
### 3. Environment Variables
|
51 |
+
|
52 |
+
Set your database connection string with your Supabase credentials:
|
53 |
+
```bash
|
54 |
+
export DATABASE_URL="postgresql://postgres:YOUR_SUPABASE_PASSWORD@db.ckrqyjfdifjbsuuofegd.supabase.co:5432/postgres"
|
55 |
+
```
|
56 |
+
|
57 |
+
**Important**: Replace `YOUR_SUPABASE_PASSWORD` with your actual Supabase database password.
|
58 |
+
|
59 |
+
### 4. Run the Application
|
60 |
+
|
61 |
+
```bash
|
62 |
+
python app.py
|
63 |
+
```
|
64 |
+
|
65 |
+
The application will be available at `http://localhost:5000`
|
66 |
+
|
67 |
+
## Database Schema
|
68 |
+
|
69 |
+
The application uses a simple users table:
|
70 |
+
- `id`: Primary key
|
71 |
+
- `full_name`: User's full name
|
72 |
+
- `email`: Unique email address
|
73 |
+
- `password`: User password (should be hashed in production)
|
74 |
+
- `created_at`: Account creation timestamp
|
75 |
+
- `updated_at`: Last update timestamp
|
76 |
+
|
77 |
+
## Security Notes
|
78 |
+
|
79 |
+
β οΈ **Important**: This is a demo implementation. For production use:
|
80 |
+
|
81 |
+
1. Hash passwords using bcrypt or similar
|
82 |
+
2. Implement proper session management
|
83 |
+
3. Add CSRF protection
|
84 |
+
4. Use HTTPS
|
85 |
+
5. Implement rate limiting
|
86 |
+
6. Add input validation and sanitization
|
87 |
+
|
88 |
+
## File Structure
|
89 |
+
|
90 |
+
```
|
91 |
+
βββ app.py # Flask backend
|
92 |
+
βββ requirements.txt # Python dependencies
|
93 |
+
βββ database_schema.sql # Database setup
|
94 |
+
βββ setup_database.py # Database setup script
|
95 |
+
βββ test_connection.py # Database connection test
|
96 |
+
βββ books.html # Home page
|
97 |
+
βββ login.html # Login page
|
98 |
+
βββ signup.html # Signup page
|
99 |
+
βββ pricing.html # Pricing page
|
100 |
+
βββ blog.html # Blog page
|
101 |
+
βββ static-blog.html # Static blog demo
|
102 |
+
βββ community-section.html # Community section component
|
103 |
+
βββ styles.css # Global styles
|
104 |
+
```
|
105 |
+
|
106 |
+
## API Endpoints
|
107 |
+
|
108 |
+
- `POST /login` - User authentication
|
109 |
+
- `POST /signup` - User registration
|
110 |
+
- `GET /api/news` - News articles
|
111 |
+
- `GET /api/business-leaders` - Business insights
|
112 |
+
- `GET /api/dataset-info` - Dataset information
|
113 |
+
|
114 |
+
## Development
|
115 |
+
|
116 |
+
To run in development mode:
|
117 |
+
```bash
|
118 |
+
export FLASK_ENV=development
|
119 |
+
python app.py
|
120 |
+
```
|
121 |
+
|
122 |
+
## Contributing
|
123 |
+
|
124 |
+
1. Fork the repository
|
125 |
+
2. Create a feature branch
|
126 |
+
3. Make your changes
|
127 |
+
4. Test thoroughly
|
128 |
+
5. Submit a pull request
|
129 |
+
|
130 |
+
## License
|
131 |
+
|
132 |
+
This project is for educational purposes. Please ensure you have proper licenses for any content used.
|
133 |
+
|
134 |
+
|
booknap project/animated-tabs.css
ADDED
@@ -0,0 +1,441 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* Animated Tabs CSS - Blinkist Style */
|
2 |
+
|
3 |
+
/* Animated Tabs Section */
|
4 |
+
.animated-tabs-section {
|
5 |
+
padding: 6rem 0;
|
6 |
+
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
|
7 |
+
overflow: hidden;
|
8 |
+
min-height: 100vh;
|
9 |
+
display: flex;
|
10 |
+
align-items: center;
|
11 |
+
}
|
12 |
+
|
13 |
+
.tabs-container {
|
14 |
+
max-width: 1200px;
|
15 |
+
margin: 0 auto;
|
16 |
+
padding: 0 20px;
|
17 |
+
width: 100%;
|
18 |
+
}
|
19 |
+
|
20 |
+
.tabs-header {
|
21 |
+
text-align: center;
|
22 |
+
margin-bottom: 4rem;
|
23 |
+
}
|
24 |
+
|
25 |
+
.tabs-header h2 {
|
26 |
+
font-size: 3rem;
|
27 |
+
font-weight: 700;
|
28 |
+
color: #2d3748;
|
29 |
+
margin-bottom: 1rem;
|
30 |
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
31 |
+
-webkit-background-clip: text;
|
32 |
+
-webkit-text-fill-color: transparent;
|
33 |
+
background-clip: text;
|
34 |
+
}
|
35 |
+
|
36 |
+
.tabs-header p {
|
37 |
+
font-size: 1.2rem;
|
38 |
+
color: #4a5568;
|
39 |
+
max-width: 600px;
|
40 |
+
margin: 0 auto;
|
41 |
+
}
|
42 |
+
|
43 |
+
.tabs-wrapper {
|
44 |
+
display: flex;
|
45 |
+
flex-direction: column;
|
46 |
+
align-items: center;
|
47 |
+
gap: 3rem;
|
48 |
+
}
|
49 |
+
|
50 |
+
/* Tab Navigation */
|
51 |
+
.tabs-nav {
|
52 |
+
display: flex;
|
53 |
+
background: white;
|
54 |
+
border-radius: 50px;
|
55 |
+
padding: 0.5rem;
|
56 |
+
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
|
57 |
+
position: relative;
|
58 |
+
overflow: hidden;
|
59 |
+
}
|
60 |
+
|
61 |
+
.tab-button {
|
62 |
+
background: none;
|
63 |
+
border: none;
|
64 |
+
padding: 1rem 2rem;
|
65 |
+
border-radius: 40px;
|
66 |
+
font-size: 1rem;
|
67 |
+
font-weight: 600;
|
68 |
+
color: #4a5568;
|
69 |
+
cursor: pointer;
|
70 |
+
transition: all 0.3s ease;
|
71 |
+
position: relative;
|
72 |
+
z-index: 2;
|
73 |
+
white-space: nowrap;
|
74 |
+
display: flex;
|
75 |
+
align-items: center;
|
76 |
+
gap: 0.5rem;
|
77 |
+
}
|
78 |
+
|
79 |
+
.tab-button.active {
|
80 |
+
color: white;
|
81 |
+
}
|
82 |
+
|
83 |
+
.tab-button i {
|
84 |
+
font-size: 1.2rem;
|
85 |
+
}
|
86 |
+
|
87 |
+
.tab-slider {
|
88 |
+
position: absolute;
|
89 |
+
top: 0.5rem;
|
90 |
+
left: 0.5rem;
|
91 |
+
height: calc(100% - 1rem);
|
92 |
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
93 |
+
border-radius: 40px;
|
94 |
+
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
95 |
+
z-index: 1;
|
96 |
+
}
|
97 |
+
|
98 |
+
/* Tab Content */
|
99 |
+
.tabs-content {
|
100 |
+
width: 100%;
|
101 |
+
max-width: 1000px;
|
102 |
+
position: relative;
|
103 |
+
}
|
104 |
+
|
105 |
+
.tab-panel {
|
106 |
+
display: none;
|
107 |
+
animation: fadeInUp 0.6s ease-out;
|
108 |
+
}
|
109 |
+
|
110 |
+
.tab-panel.active {
|
111 |
+
display: block;
|
112 |
+
}
|
113 |
+
|
114 |
+
.tab-panel-content {
|
115 |
+
background: white;
|
116 |
+
border-radius: 20px;
|
117 |
+
padding: 3rem;
|
118 |
+
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
|
119 |
+
position: relative;
|
120 |
+
overflow: hidden;
|
121 |
+
}
|
122 |
+
|
123 |
+
.tab-panel-content::before {
|
124 |
+
content: '';
|
125 |
+
position: absolute;
|
126 |
+
top: 0;
|
127 |
+
left: 0;
|
128 |
+
right: 0;
|
129 |
+
height: 4px;
|
130 |
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
131 |
+
}
|
132 |
+
|
133 |
+
/* Tab-specific styles */
|
134 |
+
.read-tab {
|
135 |
+
display: grid;
|
136 |
+
grid-template-columns: 1fr 1fr;
|
137 |
+
gap: 3rem;
|
138 |
+
align-items: center;
|
139 |
+
}
|
140 |
+
|
141 |
+
.read-content h3 {
|
142 |
+
font-size: 2rem;
|
143 |
+
font-weight: 700;
|
144 |
+
color: #2d3748;
|
145 |
+
margin-bottom: 1rem;
|
146 |
+
}
|
147 |
+
|
148 |
+
.read-content p {
|
149 |
+
font-size: 1.1rem;
|
150 |
+
color: #4a5568;
|
151 |
+
line-height: 1.7;
|
152 |
+
margin-bottom: 2rem;
|
153 |
+
}
|
154 |
+
|
155 |
+
.read-features {
|
156 |
+
display: flex;
|
157 |
+
flex-direction: column;
|
158 |
+
gap: 1rem;
|
159 |
+
}
|
160 |
+
|
161 |
+
.read-feature {
|
162 |
+
display: flex;
|
163 |
+
align-items: center;
|
164 |
+
gap: 1rem;
|
165 |
+
padding: 1rem;
|
166 |
+
background: #f8fafc;
|
167 |
+
border-radius: 10px;
|
168 |
+
transition: all 0.3s ease;
|
169 |
+
}
|
170 |
+
|
171 |
+
.read-feature:hover {
|
172 |
+
background: #e2e8f0;
|
173 |
+
transform: translateX(10px);
|
174 |
+
}
|
175 |
+
|
176 |
+
.read-feature i {
|
177 |
+
font-size: 1.5rem;
|
178 |
+
color: #667eea;
|
179 |
+
width: 40px;
|
180 |
+
height: 40px;
|
181 |
+
display: flex;
|
182 |
+
align-items: center;
|
183 |
+
justify-content: center;
|
184 |
+
background: white;
|
185 |
+
border-radius: 50%;
|
186 |
+
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.2);
|
187 |
+
}
|
188 |
+
|
189 |
+
.read-feature-text h4 {
|
190 |
+
font-weight: 600;
|
191 |
+
color: #2d3748;
|
192 |
+
margin-bottom: 0.25rem;
|
193 |
+
}
|
194 |
+
|
195 |
+
.read-feature-text p {
|
196 |
+
font-size: 0.9rem;
|
197 |
+
color: #4a5568;
|
198 |
+
margin: 0;
|
199 |
+
}
|
200 |
+
|
201 |
+
.read-visual {
|
202 |
+
position: relative;
|
203 |
+
text-align: center;
|
204 |
+
}
|
205 |
+
|
206 |
+
.read-visual img {
|
207 |
+
max-width: 100%;
|
208 |
+
height: auto;
|
209 |
+
border-radius: 15px;
|
210 |
+
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
|
211 |
+
}
|
212 |
+
|
213 |
+
.listen-tab {
|
214 |
+
display: grid;
|
215 |
+
grid-template-columns: 1fr 1fr;
|
216 |
+
gap: 3rem;
|
217 |
+
align-items: center;
|
218 |
+
}
|
219 |
+
|
220 |
+
.listen-content h3 {
|
221 |
+
font-size: 2rem;
|
222 |
+
font-weight: 700;
|
223 |
+
color: #2d3748;
|
224 |
+
margin-bottom: 1rem;
|
225 |
+
}
|
226 |
+
|
227 |
+
.listen-content p {
|
228 |
+
font-size: 1.1rem;
|
229 |
+
color: #4a5568;
|
230 |
+
line-height: 1.7;
|
231 |
+
margin-bottom: 2rem;
|
232 |
+
}
|
233 |
+
|
234 |
+
.listen-features {
|
235 |
+
display: flex;
|
236 |
+
flex-direction: column;
|
237 |
+
gap: 1rem;
|
238 |
+
}
|
239 |
+
|
240 |
+
.listen-feature {
|
241 |
+
display: flex;
|
242 |
+
align-items: center;
|
243 |
+
gap: 1rem;
|
244 |
+
padding: 1rem;
|
245 |
+
background: #f8fafc;
|
246 |
+
border-radius: 10px;
|
247 |
+
transition: all 0.3s ease;
|
248 |
+
}
|
249 |
+
|
250 |
+
.listen-feature:hover {
|
251 |
+
background: #e2e8f0;
|
252 |
+
transform: translateX(10px);
|
253 |
+
}
|
254 |
+
|
255 |
+
.listen-feature i {
|
256 |
+
font-size: 1.5rem;
|
257 |
+
color: #667eea;
|
258 |
+
width: 40px;
|
259 |
+
height: 40px;
|
260 |
+
display: flex;
|
261 |
+
align-items: center;
|
262 |
+
justify-content: center;
|
263 |
+
background: white;
|
264 |
+
border-radius: 50%;
|
265 |
+
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.2);
|
266 |
+
}
|
267 |
+
|
268 |
+
.listen-feature-text h4 {
|
269 |
+
font-weight: 600;
|
270 |
+
color: #2d3748;
|
271 |
+
margin-bottom: 0.25rem;
|
272 |
+
}
|
273 |
+
|
274 |
+
.listen-feature-text p {
|
275 |
+
font-size: 0.9rem;
|
276 |
+
color: #4a5568;
|
277 |
+
margin: 0;
|
278 |
+
}
|
279 |
+
|
280 |
+
.listen-visual {
|
281 |
+
position: relative;
|
282 |
+
text-align: center;
|
283 |
+
}
|
284 |
+
|
285 |
+
.listen-visual img {
|
286 |
+
max-width: 100%;
|
287 |
+
height: auto;
|
288 |
+
border-radius: 15px;
|
289 |
+
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
|
290 |
+
}
|
291 |
+
|
292 |
+
.learn-tab {
|
293 |
+
text-align: center;
|
294 |
+
}
|
295 |
+
|
296 |
+
.learn-content h3 {
|
297 |
+
font-size: 2.5rem;
|
298 |
+
font-weight: 700;
|
299 |
+
color: #2d3748;
|
300 |
+
margin-bottom: 1.5rem;
|
301 |
+
}
|
302 |
+
|
303 |
+
.learn-content p {
|
304 |
+
font-size: 1.2rem;
|
305 |
+
color: #4a5568;
|
306 |
+
line-height: 1.7;
|
307 |
+
margin-bottom: 3rem;
|
308 |
+
max-width: 600px;
|
309 |
+
margin-left: auto;
|
310 |
+
margin-right: auto;
|
311 |
+
}
|
312 |
+
|
313 |
+
.learn-grid {
|
314 |
+
display: grid;
|
315 |
+
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
316 |
+
gap: 2rem;
|
317 |
+
margin-top: 3rem;
|
318 |
+
}
|
319 |
+
|
320 |
+
.learn-card {
|
321 |
+
background: #f8fafc;
|
322 |
+
border-radius: 15px;
|
323 |
+
padding: 2rem;
|
324 |
+
transition: all 0.3s ease;
|
325 |
+
border: 2px solid transparent;
|
326 |
+
}
|
327 |
+
|
328 |
+
.learn-card:hover {
|
329 |
+
background: white;
|
330 |
+
border-color: #667eea;
|
331 |
+
transform: translateY(-10px);
|
332 |
+
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
|
333 |
+
}
|
334 |
+
|
335 |
+
.learn-card i {
|
336 |
+
font-size: 3rem;
|
337 |
+
color: #667eea;
|
338 |
+
margin-bottom: 1rem;
|
339 |
+
}
|
340 |
+
|
341 |
+
.learn-card h4 {
|
342 |
+
font-size: 1.25rem;
|
343 |
+
font-weight: 600;
|
344 |
+
color: #2d3748;
|
345 |
+
margin-bottom: 1rem;
|
346 |
+
}
|
347 |
+
|
348 |
+
.learn-card p {
|
349 |
+
font-size: 1rem;
|
350 |
+
color: #4a5568;
|
351 |
+
line-height: 1.6;
|
352 |
+
margin: 0;
|
353 |
+
}
|
354 |
+
|
355 |
+
/* Animations */
|
356 |
+
@keyframes fadeInUp {
|
357 |
+
from {
|
358 |
+
opacity: 0;
|
359 |
+
transform: translateY(30px);
|
360 |
+
}
|
361 |
+
to {
|
362 |
+
opacity: 1;
|
363 |
+
transform: translateY(0);
|
364 |
+
}
|
365 |
+
}
|
366 |
+
|
367 |
+
@keyframes slideIn {
|
368 |
+
from {
|
369 |
+
opacity: 0;
|
370 |
+
transform: translateX(-30px);
|
371 |
+
}
|
372 |
+
to {
|
373 |
+
opacity: 1;
|
374 |
+
transform: translateX(0);
|
375 |
+
}
|
376 |
+
}
|
377 |
+
|
378 |
+
/* Responsive Design */
|
379 |
+
@media (max-width: 768px) {
|
380 |
+
.tabs-header h2 {
|
381 |
+
font-size: 2rem;
|
382 |
+
}
|
383 |
+
|
384 |
+
.tabs-nav {
|
385 |
+
flex-direction: column;
|
386 |
+
border-radius: 20px;
|
387 |
+
padding: 0.25rem;
|
388 |
+
}
|
389 |
+
|
390 |
+
.tab-button {
|
391 |
+
padding: 0.75rem 1.5rem;
|
392 |
+
font-size: 0.9rem;
|
393 |
+
}
|
394 |
+
|
395 |
+
.tab-slider {
|
396 |
+
display: none;
|
397 |
+
}
|
398 |
+
|
399 |
+
.tab-button.active {
|
400 |
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
401 |
+
color: white;
|
402 |
+
}
|
403 |
+
|
404 |
+
.read-tab,
|
405 |
+
.listen-tab {
|
406 |
+
grid-template-columns: 1fr;
|
407 |
+
gap: 2rem;
|
408 |
+
}
|
409 |
+
|
410 |
+
.tab-panel-content {
|
411 |
+
padding: 2rem;
|
412 |
+
}
|
413 |
+
|
414 |
+
.learn-grid {
|
415 |
+
grid-template-columns: 1fr;
|
416 |
+
}
|
417 |
+
}
|
418 |
+
|
419 |
+
@media (max-width: 480px) {
|
420 |
+
.tabs-header h2 {
|
421 |
+
font-size: 1.75rem;
|
422 |
+
}
|
423 |
+
|
424 |
+
.tabs-header p {
|
425 |
+
font-size: 1rem;
|
426 |
+
}
|
427 |
+
|
428 |
+
.tab-panel-content {
|
429 |
+
padding: 1.5rem;
|
430 |
+
}
|
431 |
+
|
432 |
+
.read-content h3,
|
433 |
+
.listen-content h3 {
|
434 |
+
font-size: 1.5rem;
|
435 |
+
}
|
436 |
+
|
437 |
+
.learn-content h3 {
|
438 |
+
font-size: 2rem;
|
439 |
+
}
|
440 |
+
}
|
441 |
+
|
booknap project/animated-tabs.html
ADDED
@@ -0,0 +1,658 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8">
|
5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6 |
+
<title>BookNap - Animated Tabs</title>
|
7 |
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
8 |
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
9 |
+
<style>
|
10 |
+
/* Reset and Base Styles */
|
11 |
+
* {
|
12 |
+
margin: 0;
|
13 |
+
padding: 0;
|
14 |
+
box-sizing: border-box;
|
15 |
+
}
|
16 |
+
|
17 |
+
body {
|
18 |
+
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
19 |
+
line-height: 1.6;
|
20 |
+
color: #333;
|
21 |
+
background-color: #f8fafc;
|
22 |
+
}
|
23 |
+
|
24 |
+
.container {
|
25 |
+
max-width: 1200px;
|
26 |
+
margin: 0 auto;
|
27 |
+
padding: 0 20px;
|
28 |
+
}
|
29 |
+
|
30 |
+
/* Animated Tabs Section - Blinkist Style */
|
31 |
+
.animated-tabs-section {
|
32 |
+
padding: 6rem 0;
|
33 |
+
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
|
34 |
+
overflow: hidden;
|
35 |
+
min-height: 100vh;
|
36 |
+
display: flex;
|
37 |
+
align-items: center;
|
38 |
+
}
|
39 |
+
|
40 |
+
.tabs-container {
|
41 |
+
max-width: 1200px;
|
42 |
+
margin: 0 auto;
|
43 |
+
padding: 0 20px;
|
44 |
+
width: 100%;
|
45 |
+
}
|
46 |
+
|
47 |
+
.tabs-header {
|
48 |
+
text-align: center;
|
49 |
+
margin-bottom: 4rem;
|
50 |
+
}
|
51 |
+
|
52 |
+
.tabs-header h2 {
|
53 |
+
font-size: 3rem;
|
54 |
+
font-weight: 700;
|
55 |
+
color: #2d3748;
|
56 |
+
margin-bottom: 1rem;
|
57 |
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
58 |
+
-webkit-background-clip: text;
|
59 |
+
-webkit-text-fill-color: transparent;
|
60 |
+
background-clip: text;
|
61 |
+
}
|
62 |
+
|
63 |
+
.tabs-header p {
|
64 |
+
font-size: 1.2rem;
|
65 |
+
color: #4a5568;
|
66 |
+
max-width: 600px;
|
67 |
+
margin: 0 auto;
|
68 |
+
}
|
69 |
+
|
70 |
+
.tabs-wrapper {
|
71 |
+
display: flex;
|
72 |
+
flex-direction: column;
|
73 |
+
align-items: center;
|
74 |
+
gap: 3rem;
|
75 |
+
}
|
76 |
+
|
77 |
+
.tabs-nav {
|
78 |
+
display: flex;
|
79 |
+
background: white;
|
80 |
+
border-radius: 50px;
|
81 |
+
padding: 0.5rem;
|
82 |
+
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
|
83 |
+
position: relative;
|
84 |
+
overflow: hidden;
|
85 |
+
}
|
86 |
+
|
87 |
+
.tab-button {
|
88 |
+
background: none;
|
89 |
+
border: none;
|
90 |
+
padding: 1rem 2rem;
|
91 |
+
border-radius: 40px;
|
92 |
+
font-size: 1rem;
|
93 |
+
font-weight: 600;
|
94 |
+
color: #4a5568;
|
95 |
+
cursor: pointer;
|
96 |
+
transition: all 0.3s ease;
|
97 |
+
position: relative;
|
98 |
+
z-index: 2;
|
99 |
+
white-space: nowrap;
|
100 |
+
display: flex;
|
101 |
+
align-items: center;
|
102 |
+
gap: 0.5rem;
|
103 |
+
}
|
104 |
+
|
105 |
+
.tab-button.active {
|
106 |
+
color: white;
|
107 |
+
}
|
108 |
+
|
109 |
+
.tab-button i {
|
110 |
+
font-size: 1.2rem;
|
111 |
+
}
|
112 |
+
|
113 |
+
.tab-slider {
|
114 |
+
position: absolute;
|
115 |
+
top: 0.5rem;
|
116 |
+
left: 0.5rem;
|
117 |
+
height: calc(100% - 1rem);
|
118 |
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
119 |
+
border-radius: 40px;
|
120 |
+
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
121 |
+
z-index: 1;
|
122 |
+
}
|
123 |
+
|
124 |
+
.tabs-content {
|
125 |
+
width: 100%;
|
126 |
+
max-width: 1000px;
|
127 |
+
position: relative;
|
128 |
+
}
|
129 |
+
|
130 |
+
.tab-panel {
|
131 |
+
display: none;
|
132 |
+
animation: fadeInUp 0.6s ease-out;
|
133 |
+
}
|
134 |
+
|
135 |
+
.tab-panel.active {
|
136 |
+
display: block;
|
137 |
+
}
|
138 |
+
|
139 |
+
.tab-panel-content {
|
140 |
+
background: white;
|
141 |
+
border-radius: 20px;
|
142 |
+
padding: 3rem;
|
143 |
+
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
|
144 |
+
position: relative;
|
145 |
+
overflow: hidden;
|
146 |
+
}
|
147 |
+
|
148 |
+
.tab-panel-content::before {
|
149 |
+
content: '';
|
150 |
+
position: absolute;
|
151 |
+
top: 0;
|
152 |
+
left: 0;
|
153 |
+
right: 0;
|
154 |
+
height: 4px;
|
155 |
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
156 |
+
}
|
157 |
+
|
158 |
+
/* Tab-specific styles */
|
159 |
+
.read-tab {
|
160 |
+
display: grid;
|
161 |
+
grid-template-columns: 1fr 1fr;
|
162 |
+
gap: 3rem;
|
163 |
+
align-items: center;
|
164 |
+
}
|
165 |
+
|
166 |
+
.read-content h3 {
|
167 |
+
font-size: 2rem;
|
168 |
+
font-weight: 700;
|
169 |
+
color: #2d3748;
|
170 |
+
margin-bottom: 1rem;
|
171 |
+
}
|
172 |
+
|
173 |
+
.read-content p {
|
174 |
+
font-size: 1.1rem;
|
175 |
+
color: #4a5568;
|
176 |
+
line-height: 1.7;
|
177 |
+
margin-bottom: 2rem;
|
178 |
+
}
|
179 |
+
|
180 |
+
.read-features {
|
181 |
+
display: flex;
|
182 |
+
flex-direction: column;
|
183 |
+
gap: 1rem;
|
184 |
+
}
|
185 |
+
|
186 |
+
.read-feature {
|
187 |
+
display: flex;
|
188 |
+
align-items: center;
|
189 |
+
gap: 1rem;
|
190 |
+
padding: 1rem;
|
191 |
+
background: #f8fafc;
|
192 |
+
border-radius: 10px;
|
193 |
+
transition: all 0.3s ease;
|
194 |
+
}
|
195 |
+
|
196 |
+
.read-feature:hover {
|
197 |
+
background: #e2e8f0;
|
198 |
+
transform: translateX(10px);
|
199 |
+
}
|
200 |
+
|
201 |
+
.read-feature i {
|
202 |
+
font-size: 1.5rem;
|
203 |
+
color: #667eea;
|
204 |
+
width: 40px;
|
205 |
+
height: 40px;
|
206 |
+
display: flex;
|
207 |
+
align-items: center;
|
208 |
+
justify-content: center;
|
209 |
+
background: white;
|
210 |
+
border-radius: 50%;
|
211 |
+
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.2);
|
212 |
+
}
|
213 |
+
|
214 |
+
.read-feature-text h4 {
|
215 |
+
font-weight: 600;
|
216 |
+
color: #2d3748;
|
217 |
+
margin-bottom: 0.25rem;
|
218 |
+
}
|
219 |
+
|
220 |
+
.read-feature-text p {
|
221 |
+
font-size: 0.9rem;
|
222 |
+
color: #4a5568;
|
223 |
+
margin: 0;
|
224 |
+
}
|
225 |
+
|
226 |
+
.read-visual {
|
227 |
+
position: relative;
|
228 |
+
text-align: center;
|
229 |
+
}
|
230 |
+
|
231 |
+
.read-visual img {
|
232 |
+
max-width: 100%;
|
233 |
+
height: auto;
|
234 |
+
border-radius: 15px;
|
235 |
+
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
|
236 |
+
}
|
237 |
+
|
238 |
+
.listen-tab {
|
239 |
+
display: grid;
|
240 |
+
grid-template-columns: 1fr 1fr;
|
241 |
+
gap: 3rem;
|
242 |
+
align-items: center;
|
243 |
+
}
|
244 |
+
|
245 |
+
.listen-content h3 {
|
246 |
+
font-size: 2rem;
|
247 |
+
font-weight: 700;
|
248 |
+
color: #2d3748;
|
249 |
+
margin-bottom: 1rem;
|
250 |
+
}
|
251 |
+
|
252 |
+
.listen-content p {
|
253 |
+
font-size: 1.1rem;
|
254 |
+
color: #4a5568;
|
255 |
+
line-height: 1.7;
|
256 |
+
margin-bottom: 2rem;
|
257 |
+
}
|
258 |
+
|
259 |
+
.listen-features {
|
260 |
+
display: flex;
|
261 |
+
flex-direction: column;
|
262 |
+
gap: 1rem;
|
263 |
+
}
|
264 |
+
|
265 |
+
.listen-feature {
|
266 |
+
display: flex;
|
267 |
+
align-items: center;
|
268 |
+
gap: 1rem;
|
269 |
+
padding: 1rem;
|
270 |
+
background: #f8fafc;
|
271 |
+
border-radius: 10px;
|
272 |
+
transition: all 0.3s ease;
|
273 |
+
}
|
274 |
+
|
275 |
+
.listen-feature:hover {
|
276 |
+
background: #e2e8f0;
|
277 |
+
transform: translateX(10px);
|
278 |
+
}
|
279 |
+
|
280 |
+
.listen-feature i {
|
281 |
+
font-size: 1.5rem;
|
282 |
+
color: #667eea;
|
283 |
+
width: 40px;
|
284 |
+
height: 40px;
|
285 |
+
display: flex;
|
286 |
+
align-items: center;
|
287 |
+
justify-content: center;
|
288 |
+
background: white;
|
289 |
+
border-radius: 50%;
|
290 |
+
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.2);
|
291 |
+
}
|
292 |
+
|
293 |
+
.listen-feature-text h4 {
|
294 |
+
font-weight: 600;
|
295 |
+
color: #2d3748;
|
296 |
+
margin-bottom: 0.25rem;
|
297 |
+
}
|
298 |
+
|
299 |
+
.listen-feature-text p {
|
300 |
+
font-size: 0.9rem;
|
301 |
+
color: #4a5568;
|
302 |
+
margin: 0;
|
303 |
+
}
|
304 |
+
|
305 |
+
.listen-visual {
|
306 |
+
position: relative;
|
307 |
+
text-align: center;
|
308 |
+
}
|
309 |
+
|
310 |
+
.listen-visual img {
|
311 |
+
max-width: 100%;
|
312 |
+
height: auto;
|
313 |
+
border-radius: 15px;
|
314 |
+
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
|
315 |
+
}
|
316 |
+
|
317 |
+
.learn-tab {
|
318 |
+
text-align: center;
|
319 |
+
}
|
320 |
+
|
321 |
+
.learn-content h3 {
|
322 |
+
font-size: 2.5rem;
|
323 |
+
font-weight: 700;
|
324 |
+
color: #2d3748;
|
325 |
+
margin-bottom: 1.5rem;
|
326 |
+
}
|
327 |
+
|
328 |
+
.learn-content p {
|
329 |
+
font-size: 1.2rem;
|
330 |
+
color: #4a5568;
|
331 |
+
line-height: 1.7;
|
332 |
+
margin-bottom: 3rem;
|
333 |
+
max-width: 600px;
|
334 |
+
margin-left: auto;
|
335 |
+
margin-right: auto;
|
336 |
+
}
|
337 |
+
|
338 |
+
.learn-grid {
|
339 |
+
display: grid;
|
340 |
+
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
341 |
+
gap: 2rem;
|
342 |
+
margin-top: 3rem;
|
343 |
+
}
|
344 |
+
|
345 |
+
.learn-card {
|
346 |
+
background: #f8fafc;
|
347 |
+
border-radius: 15px;
|
348 |
+
padding: 2rem;
|
349 |
+
transition: all 0.3s ease;
|
350 |
+
border: 2px solid transparent;
|
351 |
+
}
|
352 |
+
|
353 |
+
.learn-card:hover {
|
354 |
+
background: white;
|
355 |
+
border-color: #667eea;
|
356 |
+
transform: translateY(-10px);
|
357 |
+
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
|
358 |
+
}
|
359 |
+
|
360 |
+
.learn-card i {
|
361 |
+
font-size: 3rem;
|
362 |
+
color: #667eea;
|
363 |
+
margin-bottom: 1rem;
|
364 |
+
}
|
365 |
+
|
366 |
+
.learn-card h4 {
|
367 |
+
font-size: 1.25rem;
|
368 |
+
font-weight: 600;
|
369 |
+
color: #2d3748;
|
370 |
+
margin-bottom: 1rem;
|
371 |
+
}
|
372 |
+
|
373 |
+
.learn-card p {
|
374 |
+
font-size: 1rem;
|
375 |
+
color: #4a5568;
|
376 |
+
line-height: 1.6;
|
377 |
+
margin: 0;
|
378 |
+
}
|
379 |
+
|
380 |
+
/* Animations */
|
381 |
+
@keyframes fadeInUp {
|
382 |
+
from {
|
383 |
+
opacity: 0;
|
384 |
+
transform: translateY(30px);
|
385 |
+
}
|
386 |
+
to {
|
387 |
+
opacity: 1;
|
388 |
+
transform: translateY(0);
|
389 |
+
}
|
390 |
+
}
|
391 |
+
|
392 |
+
@keyframes slideIn {
|
393 |
+
from {
|
394 |
+
opacity: 0;
|
395 |
+
transform: translateX(-30px);
|
396 |
+
}
|
397 |
+
to {
|
398 |
+
opacity: 1;
|
399 |
+
transform: translateX(0);
|
400 |
+
}
|
401 |
+
}
|
402 |
+
|
403 |
+
/* Responsive Design */
|
404 |
+
@media (max-width: 768px) {
|
405 |
+
.tabs-header h2 {
|
406 |
+
font-size: 2rem;
|
407 |
+
}
|
408 |
+
|
409 |
+
.tabs-nav {
|
410 |
+
flex-direction: column;
|
411 |
+
border-radius: 20px;
|
412 |
+
padding: 0.25rem;
|
413 |
+
}
|
414 |
+
|
415 |
+
.tab-button {
|
416 |
+
padding: 0.75rem 1.5rem;
|
417 |
+
font-size: 0.9rem;
|
418 |
+
}
|
419 |
+
|
420 |
+
.tab-slider {
|
421 |
+
display: none;
|
422 |
+
}
|
423 |
+
|
424 |
+
.tab-button.active {
|
425 |
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
426 |
+
color: white;
|
427 |
+
}
|
428 |
+
|
429 |
+
.read-tab,
|
430 |
+
.listen-tab {
|
431 |
+
grid-template-columns: 1fr;
|
432 |
+
gap: 2rem;
|
433 |
+
}
|
434 |
+
|
435 |
+
.tab-panel-content {
|
436 |
+
padding: 2rem;
|
437 |
+
}
|
438 |
+
|
439 |
+
.learn-grid {
|
440 |
+
grid-template-columns: 1fr;
|
441 |
+
}
|
442 |
+
}
|
443 |
+
|
444 |
+
@media (max-width: 480px) {
|
445 |
+
.tabs-header h2 {
|
446 |
+
font-size: 1.75rem;
|
447 |
+
}
|
448 |
+
|
449 |
+
.tabs-header p {
|
450 |
+
font-size: 1rem;
|
451 |
+
}
|
452 |
+
|
453 |
+
.tab-panel-content {
|
454 |
+
padding: 1.5rem;
|
455 |
+
}
|
456 |
+
|
457 |
+
.read-content h3,
|
458 |
+
.listen-content h3 {
|
459 |
+
font-size: 1.5rem;
|
460 |
+
}
|
461 |
+
|
462 |
+
.learn-content h3 {
|
463 |
+
font-size: 2rem;
|
464 |
+
}
|
465 |
+
}
|
466 |
+
</style>
|
467 |
+
</head>
|
468 |
+
<body>
|
469 |
+
<section class="animated-tabs-section">
|
470 |
+
<div class="tabs-container">
|
471 |
+
<div class="tabs-header">
|
472 |
+
<h2>Bite-sized bestsellers</h2>
|
473 |
+
<p>Get powerful ideas in minutesβnot hours or days with our summaries of today's most transformative books.</p>
|
474 |
+
</div>
|
475 |
+
|
476 |
+
<div class="tabs-wrapper">
|
477 |
+
<div class="tabs-nav">
|
478 |
+
<div class="tab-slider"></div>
|
479 |
+
<button class="tab-button active" data-tab="read">
|
480 |
+
<i class="fas fa-book-open"></i>
|
481 |
+
Read
|
482 |
+
</button>
|
483 |
+
<button class="tab-button" data-tab="listen">
|
484 |
+
<i class="fas fa-headphones"></i>
|
485 |
+
Listen
|
486 |
+
</button>
|
487 |
+
<button class="tab-button" data-tab="learn">
|
488 |
+
<i class="fas fa-graduation-cap"></i>
|
489 |
+
Learn
|
490 |
+
</button>
|
491 |
+
</div>
|
492 |
+
|
493 |
+
<div class="tabs-content">
|
494 |
+
<!-- Read Tab -->
|
495 |
+
<div class="tab-panel active" id="read">
|
496 |
+
<div class="tab-panel-content">
|
497 |
+
<div class="read-tab">
|
498 |
+
<div class="read-content">
|
499 |
+
<h3>Read powerful insights</h3>
|
500 |
+
<p>Transform your reading experience with concise, well-structured summaries that capture the essence of bestselling books. Perfect for busy professionals who want to stay ahead.</p>
|
501 |
+
|
502 |
+
<div class="read-features">
|
503 |
+
<div class="read-feature">
|
504 |
+
<i class="fas fa-clock"></i>
|
505 |
+
<div class="read-feature-text">
|
506 |
+
<h4>15-minute reads</h4>
|
507 |
+
<p>Get the key insights in just 15 minutes</p>
|
508 |
+
</div>
|
509 |
+
</div>
|
510 |
+
<div class="read-feature">
|
511 |
+
<i class="fas fa-mobile-alt"></i>
|
512 |
+
<div class="read-feature-text">
|
513 |
+
<h4>Read anywhere</h4>
|
514 |
+
<p>Sync across all your devices seamlessly</p>
|
515 |
+
</div>
|
516 |
+
</div>
|
517 |
+
<div class="read-feature">
|
518 |
+
<i class="fas fa-bookmark"></i>
|
519 |
+
<div class="read-feature-text">
|
520 |
+
<h4>Save highlights</h4>
|
521 |
+
<p>Mark important passages for later review</p>
|
522 |
+
</div>
|
523 |
+
</div>
|
524 |
+
</div>
|
525 |
+
</div>
|
526 |
+
<div class="read-visual">
|
527 |
+
<img src="https://images.unsplash.com/photo-1481627834876-b7833e8f5570?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80" alt="Reading on mobile device">
|
528 |
+
</div>
|
529 |
+
</div>
|
530 |
+
</div>
|
531 |
+
</div>
|
532 |
+
|
533 |
+
<!-- Listen Tab -->
|
534 |
+
<div class="tab-panel" id="listen">
|
535 |
+
<div class="tab-panel-content">
|
536 |
+
<div class="listen-tab">
|
537 |
+
<div class="listen-content">
|
538 |
+
<h3>Listen on the go</h3>
|
539 |
+
<p>Turn your commute into a learning opportunity with our professionally narrated audio summaries. Perfect for multitaskers who want to absorb knowledge while staying active.</p>
|
540 |
+
|
541 |
+
<div class="listen-features">
|
542 |
+
<div class="listen-feature">
|
543 |
+
<i class="fas fa-volume-up"></i>
|
544 |
+
<div class="listen-feature-text">
|
545 |
+
<h4>Professional narration</h4>
|
546 |
+
<p>Crystal clear audio with engaging voices</p>
|
547 |
+
</div>
|
548 |
+
</div>
|
549 |
+
<div class="listen-feature">
|
550 |
+
<i class="fas fa-tachometer-alt"></i>
|
551 |
+
<div class="listen-feature-text">
|
552 |
+
<h4>Adjustable speed</h4>
|
553 |
+
<p>Listen at your preferred pace</p>
|
554 |
+
</div>
|
555 |
+
</div>
|
556 |
+
<div class="listen-feature">
|
557 |
+
<i class="fas fa-download"></i>
|
558 |
+
<div class="listen-feature-text">
|
559 |
+
<h4>Offline listening</h4>
|
560 |
+
<p>Download and listen without internet</p>
|
561 |
+
</div>
|
562 |
+
</div>
|
563 |
+
</div>
|
564 |
+
</div>
|
565 |
+
<div class="listen-visual">
|
566 |
+
<img src="https://images.unsplash.com/photo-1511671782779-c97d3d27a1d4?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80" alt="Listening to audio">
|
567 |
+
</div>
|
568 |
+
</div>
|
569 |
+
</div>
|
570 |
+
</div>
|
571 |
+
|
572 |
+
<!-- Learn Tab -->
|
573 |
+
<div class="tab-panel" id="learn">
|
574 |
+
<div class="tab-panel-content">
|
575 |
+
<div class="learn-tab">
|
576 |
+
<div class="learn-content">
|
577 |
+
<h3>An expert guides you</h3>
|
578 |
+
<p>Let a pro lead you through the most important concepts and apply what you learn with practical tools and actionable steps.</p>
|
579 |
+
|
580 |
+
<div class="learn-grid">
|
581 |
+
<div class="learn-card">
|
582 |
+
<i class="fas fa-lightbulb"></i>
|
583 |
+
<h4>Key Insights</h4>
|
584 |
+
<p>Extract the most valuable lessons from each book with expert analysis and real-world applications.</p>
|
585 |
+
</div>
|
586 |
+
<div class="learn-card">
|
587 |
+
<i class="fas fa-tasks"></i>
|
588 |
+
<h4>Action Plans</h4>
|
589 |
+
<p>Turn knowledge into action with step-by-step implementation guides and practical exercises.</p>
|
590 |
+
</div>
|
591 |
+
<div class="learn-card">
|
592 |
+
<i class="fas fa-users"></i>
|
593 |
+
<h4>Community</h4>
|
594 |
+
<p>Join discussions with like-minded learners and share insights with our growing community.</p>
|
595 |
+
</div>
|
596 |
+
</div>
|
597 |
+
</div>
|
598 |
+
</div>
|
599 |
+
</div>
|
600 |
+
</div>
|
601 |
+
</div>
|
602 |
+
</div>
|
603 |
+
</div>
|
604 |
+
</section>
|
605 |
+
|
606 |
+
<script>
|
607 |
+
// Animated Tabs JavaScript
|
608 |
+
document.addEventListener('DOMContentLoaded', function() {
|
609 |
+
const tabButtons = document.querySelectorAll('.tab-button');
|
610 |
+
const tabPanels = document.querySelectorAll('.tab-panel');
|
611 |
+
const tabSlider = document.querySelector('.tab-slider');
|
612 |
+
|
613 |
+
// Set initial slider position
|
614 |
+
const activeButton = document.querySelector('.tab-button.active');
|
615 |
+
if (activeButton && tabSlider) {
|
616 |
+
tabSlider.style.width = activeButton.offsetWidth + 'px';
|
617 |
+
tabSlider.style.left = activeButton.offsetLeft + 'px';
|
618 |
+
}
|
619 |
+
|
620 |
+
tabButtons.forEach(button => {
|
621 |
+
button.addEventListener('click', () => {
|
622 |
+
const targetTab = button.getAttribute('data-tab');
|
623 |
+
|
624 |
+
// Remove active class from all buttons and panels
|
625 |
+
tabButtons.forEach(btn => btn.classList.remove('active'));
|
626 |
+
tabPanels.forEach(panel => panel.classList.remove('active'));
|
627 |
+
|
628 |
+
// Add active class to clicked button and target panel
|
629 |
+
button.classList.add('active');
|
630 |
+
document.getElementById(targetTab).classList.add('active');
|
631 |
+
|
632 |
+
// Animate slider
|
633 |
+
if (tabSlider) {
|
634 |
+
tabSlider.style.width = button.offsetWidth + 'px';
|
635 |
+
tabSlider.style.left = button.offsetLeft + 'px';
|
636 |
+
}
|
637 |
+
});
|
638 |
+
});
|
639 |
+
|
640 |
+
// Add hover effects for mobile
|
641 |
+
if (window.innerWidth <= 768) {
|
642 |
+
tabButtons.forEach(button => {
|
643 |
+
button.addEventListener('mouseenter', () => {
|
644 |
+
if (!button.classList.contains('active')) {
|
645 |
+
button.style.transform = 'scale(1.05)';
|
646 |
+
}
|
647 |
+
});
|
648 |
+
|
649 |
+
button.addEventListener('mouseleave', () => {
|
650 |
+
button.style.transform = 'scale(1)';
|
651 |
+
});
|
652 |
+
});
|
653 |
+
}
|
654 |
+
});
|
655 |
+
</script>
|
656 |
+
</body>
|
657 |
+
</html>
|
658 |
+
|
booknap project/animated-tabs.js
ADDED
@@ -0,0 +1,143 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Animated Tabs JavaScript - Blinkist Style
|
2 |
+
class AnimatedTabs {
|
3 |
+
constructor(container) {
|
4 |
+
this.container = container;
|
5 |
+
this.tabButtons = container.querySelectorAll('.tab-button');
|
6 |
+
this.tabPanels = container.querySelectorAll('.tab-panel');
|
7 |
+
this.tabSlider = container.querySelector('.tab-slider');
|
8 |
+
this.isAnimating = false;
|
9 |
+
|
10 |
+
this.init();
|
11 |
+
}
|
12 |
+
|
13 |
+
init() {
|
14 |
+
this.setInitialState();
|
15 |
+
this.bindEvents();
|
16 |
+
this.addResponsiveBehavior();
|
17 |
+
}
|
18 |
+
|
19 |
+
setInitialState() {
|
20 |
+
// Set initial slider position
|
21 |
+
const activeButton = this.container.querySelector('.tab-button.active');
|
22 |
+
if (activeButton && this.tabSlider) {
|
23 |
+
this.updateSliderPosition(activeButton);
|
24 |
+
}
|
25 |
+
|
26 |
+
// Ensure first tab is active if none are
|
27 |
+
if (!activeButton && this.tabButtons.length > 0) {
|
28 |
+
this.tabButtons[0].classList.add('active');
|
29 |
+
this.tabPanels[0].classList.add('active');
|
30 |
+
this.updateSliderPosition(this.tabButtons[0]);
|
31 |
+
}
|
32 |
+
}
|
33 |
+
|
34 |
+
bindEvents() {
|
35 |
+
this.tabButtons.forEach(button => {
|
36 |
+
button.addEventListener('click', (e) => {
|
37 |
+
e.preventDefault();
|
38 |
+
this.switchTab(button);
|
39 |
+
});
|
40 |
+
});
|
41 |
+
}
|
42 |
+
|
43 |
+
switchTab(activeButton) {
|
44 |
+
if (this.isAnimating) return;
|
45 |
+
|
46 |
+
this.isAnimating = true;
|
47 |
+
const targetTab = activeButton.getAttribute('data-tab');
|
48 |
+
|
49 |
+
// Remove active class from all buttons and panels
|
50 |
+
this.tabButtons.forEach(btn => btn.classList.remove('active'));
|
51 |
+
this.tabPanels.forEach(panel => panel.classList.remove('active'));
|
52 |
+
|
53 |
+
// Add active class to clicked button and target panel
|
54 |
+
activeButton.classList.add('active');
|
55 |
+
const targetPanel = this.container.querySelector(`#${targetTab}`);
|
56 |
+
if (targetPanel) {
|
57 |
+
targetPanel.classList.add('active');
|
58 |
+
}
|
59 |
+
|
60 |
+
// Animate slider
|
61 |
+
this.updateSliderPosition(activeButton);
|
62 |
+
|
63 |
+
// Trigger custom event
|
64 |
+
this.container.dispatchEvent(new CustomEvent('tabChanged', {
|
65 |
+
detail: {
|
66 |
+
activeTab: targetTab,
|
67 |
+
activeButton: activeButton,
|
68 |
+
activePanel: targetPanel
|
69 |
+
}
|
70 |
+
}));
|
71 |
+
|
72 |
+
// Reset animation flag after transition
|
73 |
+
setTimeout(() => {
|
74 |
+
this.isAnimating = false;
|
75 |
+
}, 400);
|
76 |
+
}
|
77 |
+
|
78 |
+
updateSliderPosition(button) {
|
79 |
+
if (!this.tabSlider) return;
|
80 |
+
|
81 |
+
const buttonRect = button.getBoundingClientRect();
|
82 |
+
const containerRect = this.container.getBoundingClientRect();
|
83 |
+
|
84 |
+
this.tabSlider.style.width = button.offsetWidth + 'px';
|
85 |
+
this.tabSlider.style.left = (button.offsetLeft - this.container.offsetLeft) + 'px';
|
86 |
+
}
|
87 |
+
|
88 |
+
addResponsiveBehavior() {
|
89 |
+
// Handle window resize
|
90 |
+
let resizeTimeout;
|
91 |
+
window.addEventListener('resize', () => {
|
92 |
+
clearTimeout(resizeTimeout);
|
93 |
+
resizeTimeout = setTimeout(() => {
|
94 |
+
const activeButton = this.container.querySelector('.tab-button.active');
|
95 |
+
if (activeButton) {
|
96 |
+
this.updateSliderPosition(activeButton);
|
97 |
+
}
|
98 |
+
}, 100);
|
99 |
+
});
|
100 |
+
|
101 |
+
// Add hover effects for mobile
|
102 |
+
if (window.innerWidth <= 768) {
|
103 |
+
this.tabButtons.forEach(button => {
|
104 |
+
button.addEventListener('mouseenter', () => {
|
105 |
+
if (!button.classList.contains('active')) {
|
106 |
+
button.style.transform = 'scale(1.05)';
|
107 |
+
}
|
108 |
+
});
|
109 |
+
|
110 |
+
button.addEventListener('mouseleave', () => {
|
111 |
+
button.style.transform = 'scale(1)';
|
112 |
+
});
|
113 |
+
});
|
114 |
+
}
|
115 |
+
}
|
116 |
+
|
117 |
+
// Public methods
|
118 |
+
switchToTab(tabId) {
|
119 |
+
const button = this.container.querySelector(`[data-tab="${tabId}"]`);
|
120 |
+
if (button) {
|
121 |
+
this.switchTab(button);
|
122 |
+
}
|
123 |
+
}
|
124 |
+
|
125 |
+
getActiveTab() {
|
126 |
+
const activeButton = this.container.querySelector('.tab-button.active');
|
127 |
+
return activeButton ? activeButton.getAttribute('data-tab') : null;
|
128 |
+
}
|
129 |
+
}
|
130 |
+
|
131 |
+
// Auto-initialize tabs when DOM is loaded
|
132 |
+
document.addEventListener('DOMContentLoaded', function() {
|
133 |
+
const tabsContainers = document.querySelectorAll('.tabs-wrapper');
|
134 |
+
tabsContainers.forEach(container => {
|
135 |
+
new AnimatedTabs(container);
|
136 |
+
});
|
137 |
+
});
|
138 |
+
|
139 |
+
// Export for module usage
|
140 |
+
if (typeof module !== 'undefined' && module.exports) {
|
141 |
+
module.exports = AnimatedTabs;
|
142 |
+
}
|
143 |
+
|
booknap project/app.py
ADDED
@@ -0,0 +1,237 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from flask import Flask, jsonify, render_template, request
|
2 |
+
from flask_cors import CORS
|
3 |
+
from sqlalchemy import create_engine, text
|
4 |
+
import kagglehub
|
5 |
+
from kagglehub import KaggleDatasetAdapter
|
6 |
+
import pandas as pd
|
7 |
+
import os
|
8 |
+
|
9 |
+
app = Flask(__name__)
|
10 |
+
CORS(app)
|
11 |
+
|
12 |
+
# Database configuration
|
13 |
+
DATABASE_URL = os.environ.get(
|
14 |
+
"DATABASE_URL",
|
15 |
+
"postgresql://postgres:postgres@db.ckrqyjfdifjbsuuofegd.supabase.co:5432/postgres",
|
16 |
+
)
|
17 |
+
engine = create_engine(DATABASE_URL, pool_pre_ping=True)
|
18 |
+
|
19 |
+
# Download the datasets
|
20 |
+
@app.before_first_request
|
21 |
+
def download_datasets():
|
22 |
+
try:
|
23 |
+
print("Downloading datasets...")
|
24 |
+
|
25 |
+
# Download news dataset
|
26 |
+
news_path = kagglehub.dataset_download("therohk/global-news-week")
|
27 |
+
print("Path to news dataset files:", news_path)
|
28 |
+
|
29 |
+
# Download business leaders dataset
|
30 |
+
business_path = kagglehub.dataset_download("beatafaron/wisdom-from-business-leaders-and-innovators")
|
31 |
+
print("Path to business leaders dataset files:", business_path)
|
32 |
+
|
33 |
+
return {"news": news_path, "business": business_path}
|
34 |
+
except Exception as e:
|
35 |
+
print(f"Error downloading datasets: {e}")
|
36 |
+
return None
|
37 |
+
|
38 |
+
@app.route('/')
|
39 |
+
def home():
|
40 |
+
return render_template('business-leaders.html')
|
41 |
+
|
42 |
+
@app.route('/blog')
|
43 |
+
def blog():
|
44 |
+
return render_template('blog.html')
|
45 |
+
|
46 |
+
@app.route('/login', methods=['POST'])
|
47 |
+
def login():
|
48 |
+
try:
|
49 |
+
payload = request.get_json(silent=True) or request.form
|
50 |
+
email = (payload.get('email') or '').strip().lower()
|
51 |
+
password = payload.get('password') or ''
|
52 |
+
if not email or not password:
|
53 |
+
return jsonify({"error": "Email and password are required"}), 400
|
54 |
+
|
55 |
+
# Simple credentials check against users table
|
56 |
+
# Expected schema: users(id serial pk, email text unique, password text)
|
57 |
+
with engine.connect() as conn:
|
58 |
+
row = conn.execute(
|
59 |
+
text("SELECT id, email, password FROM users WHERE email = :email"),
|
60 |
+
{"email": email},
|
61 |
+
).mappings().first()
|
62 |
+
|
63 |
+
if not row:
|
64 |
+
return jsonify({"error": "Invalid credentials"}), 401
|
65 |
+
|
66 |
+
# NOTE: For demo purposes comparing plaintext. In production, store hashed passwords and verify with bcrypt.
|
67 |
+
if password != row["password"]:
|
68 |
+
return jsonify({"error": "Invalid credentials"}), 401
|
69 |
+
|
70 |
+
return jsonify({"ok": True, "user": {"id": row["id"], "email": row["email"]}})
|
71 |
+
except Exception as e:
|
72 |
+
return jsonify({"error": str(e)}), 500
|
73 |
+
|
74 |
+
@app.route('/signup', methods=['POST'])
|
75 |
+
def signup():
|
76 |
+
try:
|
77 |
+
payload = request.get_json(silent=True) or request.form
|
78 |
+
full_name = (payload.get('fullName') or '').strip()
|
79 |
+
email = (payload.get('email') or '').strip().lower()
|
80 |
+
password = payload.get('password') or ''
|
81 |
+
|
82 |
+
if not full_name or not email or not password:
|
83 |
+
return jsonify({"error": "Full name, email and password are required"}), 400
|
84 |
+
|
85 |
+
# Check if user already exists
|
86 |
+
with engine.connect() as conn:
|
87 |
+
existing_user = conn.execute(
|
88 |
+
text("SELECT id FROM users WHERE email = :email"),
|
89 |
+
{"email": email},
|
90 |
+
).mappings().first()
|
91 |
+
|
92 |
+
if existing_user:
|
93 |
+
return jsonify({"error": "User with this email already exists"}), 409
|
94 |
+
|
95 |
+
# Insert new user
|
96 |
+
# Expected schema: users(id serial pk, full_name text, email text unique, password text)
|
97 |
+
result = conn.execute(
|
98 |
+
text("INSERT INTO users (full_name, email, password) VALUES (:full_name, :email, :password) RETURNING id"),
|
99 |
+
{"full_name": full_name, "email": email, "password": password},
|
100 |
+
)
|
101 |
+
|
102 |
+
# Commit the transaction
|
103 |
+
conn.commit()
|
104 |
+
|
105 |
+
user_id = result.fetchone()[0]
|
106 |
+
|
107 |
+
return jsonify({
|
108 |
+
"message": "Account created successfully! Redirecting to login...",
|
109 |
+
"user": {"id": user_id, "full_name": full_name, "email": email}
|
110 |
+
}), 201
|
111 |
+
|
112 |
+
except Exception as e:
|
113 |
+
return jsonify({"error": str(e)}), 500
|
114 |
+
|
115 |
+
@app.route('/api/news')
|
116 |
+
def get_news():
|
117 |
+
try:
|
118 |
+
# Find the CSV file in the downloaded dataset
|
119 |
+
dataset_path = None
|
120 |
+
for root, dirs, files in os.walk('.'):
|
121 |
+
for file in files:
|
122 |
+
if file.endswith('.csv') and 'global-news' in root:
|
123 |
+
dataset_path = os.path.join(root, file)
|
124 |
+
break
|
125 |
+
if dataset_path:
|
126 |
+
break
|
127 |
+
|
128 |
+
if dataset_path:
|
129 |
+
# Read the CSV file
|
130 |
+
df = pd.read_csv(dataset_path)
|
131 |
+
|
132 |
+
# Convert to JSON format for the blog
|
133 |
+
news_data = []
|
134 |
+
for index, row in df.head(20).iterrows(): # Get first 20 articles
|
135 |
+
news_item = {
|
136 |
+
'title': row.get('title', 'No title'),
|
137 |
+
'description': row.get('description', 'No description'),
|
138 |
+
'date': row.get('date', 'No date'),
|
139 |
+
'source': row.get('source', 'Unknown source'),
|
140 |
+
'category': row.get('category', 'General')
|
141 |
+
}
|
142 |
+
news_data.append(news_item)
|
143 |
+
|
144 |
+
return jsonify(news_data)
|
145 |
+
else:
|
146 |
+
return jsonify({'error': 'News dataset file not found'})
|
147 |
+
|
148 |
+
except Exception as e:
|
149 |
+
return jsonify({'error': str(e)})
|
150 |
+
|
151 |
+
@app.route('/api/business-leaders')
|
152 |
+
def get_business_leaders():
|
153 |
+
try:
|
154 |
+
# Load the business leaders dataset using kagglehub
|
155 |
+
df = kagglehub.load_dataset(
|
156 |
+
KaggleDatasetAdapter.PANDAS,
|
157 |
+
"beatafaron/wisdom-from-business-leaders-and-innovators",
|
158 |
+
"", # Empty string for default file
|
159 |
+
)
|
160 |
+
|
161 |
+
# Convert to JSON format
|
162 |
+
business_data = []
|
163 |
+
for index, row in df.head(20).iterrows(): # Get first 20 records
|
164 |
+
business_item = {
|
165 |
+
'id': index + 1,
|
166 |
+
'quote': row.get('quote', 'No quote available'),
|
167 |
+
'author': row.get('author', 'Unknown author'),
|
168 |
+
'category': row.get('category', 'General'),
|
169 |
+
'source': row.get('source', 'Unknown source'),
|
170 |
+
'year': row.get('year', 'Unknown year')
|
171 |
+
}
|
172 |
+
business_data.append(business_item)
|
173 |
+
|
174 |
+
return jsonify(business_data)
|
175 |
+
|
176 |
+
except Exception as e:
|
177 |
+
return jsonify({'error': str(e)})
|
178 |
+
|
179 |
+
@app.route('/api/business-leaders/<int:record_id>')
|
180 |
+
def get_business_leader(record_id):
|
181 |
+
try:
|
182 |
+
# Load the business leaders dataset
|
183 |
+
df = kagglehub.load_dataset(
|
184 |
+
KaggleDatasetAdapter.PANDAS,
|
185 |
+
"beatafaron/wisdom-from-business-leaders-and-innovators",
|
186 |
+
"",
|
187 |
+
)
|
188 |
+
|
189 |
+
if record_id < len(df):
|
190 |
+
row = df.iloc[record_id]
|
191 |
+
business_item = {
|
192 |
+
'id': record_id + 1,
|
193 |
+
'quote': row.get('quote', 'No quote available'),
|
194 |
+
'author': row.get('author', 'Unknown author'),
|
195 |
+
'category': row.get('category', 'General'),
|
196 |
+
'source': row.get('source', 'Unknown source'),
|
197 |
+
'year': row.get('year', 'Unknown year')
|
198 |
+
}
|
199 |
+
return jsonify(business_item)
|
200 |
+
else:
|
201 |
+
return jsonify({'error': 'Record not found'})
|
202 |
+
|
203 |
+
except Exception as e:
|
204 |
+
return jsonify({'error': str(e)})
|
205 |
+
|
206 |
+
@app.route('/api/dataset-info')
|
207 |
+
def dataset_info():
|
208 |
+
try:
|
209 |
+
# Get info about both datasets
|
210 |
+
news_path = kagglehub.dataset_download("therohk/global-news-week")
|
211 |
+
business_path = kagglehub.dataset_download("beatafaron/wisdom-from-business-leaders-and-innovators")
|
212 |
+
|
213 |
+
return jsonify({
|
214 |
+
'status': 'success',
|
215 |
+
'datasets': {
|
216 |
+
'news': {
|
217 |
+
'name': 'Global News Week',
|
218 |
+
'path': str(news_path),
|
219 |
+
'description': 'Latest news articles from various sources'
|
220 |
+
},
|
221 |
+
'business_leaders': {
|
222 |
+
'name': 'Wisdom from Business Leaders and Innovators',
|
223 |
+
'path': str(business_path),
|
224 |
+
'description': 'Inspirational quotes and wisdom from business leaders'
|
225 |
+
}
|
226 |
+
},
|
227 |
+
'message': 'All datasets downloaded successfully'
|
228 |
+
})
|
229 |
+
except Exception as e:
|
230 |
+
return jsonify({
|
231 |
+
'status': 'error',
|
232 |
+
'error': str(e)
|
233 |
+
})
|
234 |
+
|
235 |
+
if __name__ == '__main__':
|
236 |
+
app.run(debug=True, port=5000)
|
237 |
+
|
booknap project/assets/audio/7-habits-summary.mp3
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
Placeholder audio file
|
booknap project/assets/audio/atomic-habits-summary.mp3
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
Placeholder audio file
|
booknap project/assets/audio/rich-dad-poor-dad-summary.mp3
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
Placeholder audio file
|
booknap project/assets/audio/thinking-fast-slow-summary.mp3
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
Placeholder audio file
|
booknap project/assets/covers/7-habits.jpg
ADDED
![]() |
booknap project/assets/covers/7-habits.svg
ADDED
|
booknap project/assets/covers/atomic-habits.jpg
ADDED
![]() |
booknap project/assets/covers/atomic-habits.svg
ADDED
|
booknap project/assets/covers/jane-austen-portrait.svg
ADDED
|
booknap project/assets/covers/rich-dad-poor-dad.jpg
ADDED
![]() |
booknap project/assets/covers/rich-dad-poor-dad.svg
ADDED
|
booknap project/assets/covers/start-with-why.svg
ADDED
|
booknap project/assets/covers/thinking-fast-slow.jpg
ADDED
![]() |
booknap project/assets/covers/thinking-fast-slow.svg
ADDED
|
booknap project/assets/covers/zero-to-one.svg
ADDED
|
booknap project/blog.html
ADDED
@@ -0,0 +1,612 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8" />
|
5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
6 |
+
<title>Blog - booknap</title>
|
7 |
+
<link rel="stylesheet" href="styles.css" />
|
8 |
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet" />
|
9 |
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" />
|
10 |
+
<style>
|
11 |
+
:root {
|
12 |
+
--bg: #0f172a;
|
13 |
+
--card: #0b1223;
|
14 |
+
--muted: #94a3b8;
|
15 |
+
--text: #e2e8f0;
|
16 |
+
--brand: #3b82f6;
|
17 |
+
--brand-2: #6366f1;
|
18 |
+
}
|
19 |
+
body {
|
20 |
+
background: linear-gradient(180deg, #0b1020, #0b1022 30%, #0b1124);
|
21 |
+
min-height: 100vh;
|
22 |
+
color: var(--text);
|
23 |
+
}
|
24 |
+
/* Match pricing header/nav styling */
|
25 |
+
.header { position: sticky; top: 0; -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px); background: rgba(7,10,20,0.55); z-index: 20; box-shadow: none; }
|
26 |
+
.nav { border-bottom: 1px solid rgba(255,255,255,0.06); }
|
27 |
+
.nav-logo i { color: var(--brand); }
|
28 |
+
.nav-link { color: var(--muted); text-decoration: none; font-weight: 600; }
|
29 |
+
.nav-link:hover, .nav-link.active { color: var(--text); }
|
30 |
+
|
31 |
+
/* Navigation Login Button */
|
32 |
+
.nav-container {
|
33 |
+
display: flex;
|
34 |
+
align-items: center;
|
35 |
+
gap: 2rem;
|
36 |
+
}
|
37 |
+
|
38 |
+
.nav-menu {
|
39 |
+
display: flex;
|
40 |
+
align-items: center;
|
41 |
+
gap: 2rem;
|
42 |
+
margin-left: auto;
|
43 |
+
list-style: none;
|
44 |
+
}
|
45 |
+
|
46 |
+
.nav-menu li {
|
47 |
+
position: relative;
|
48 |
+
}
|
49 |
+
|
50 |
+
.nav-login {
|
51 |
+
margin-left: 0;
|
52 |
+
}
|
53 |
+
|
54 |
+
.login-btn {
|
55 |
+
background: linear-gradient(90deg, #3b82f6, #6366f1);
|
56 |
+
color: white;
|
57 |
+
padding: 0.75rem 1.5rem;
|
58 |
+
border-radius: 8px;
|
59 |
+
text-decoration: none;
|
60 |
+
font-weight: 600;
|
61 |
+
transition: background-color 0.2s ease;
|
62 |
+
display: inline-block;
|
63 |
+
}
|
64 |
+
|
65 |
+
.login-btn:hover {
|
66 |
+
background: linear-gradient(90deg, #2563eb, #4f46e5);
|
67 |
+
}
|
68 |
+
|
69 |
+
.signup-btn {
|
70 |
+
background: transparent;
|
71 |
+
color: var(--text);
|
72 |
+
padding: 0.75rem 1.5rem;
|
73 |
+
border: 2px solid rgba(255, 255, 255, 0.2);
|
74 |
+
border-radius: 8px;
|
75 |
+
text-decoration: none;
|
76 |
+
font-weight: 600;
|
77 |
+
transition: all 0.2s ease;
|
78 |
+
display: inline-block;
|
79 |
+
margin-left: 0.5rem;
|
80 |
+
}
|
81 |
+
|
82 |
+
.signup-btn:hover {
|
83 |
+
background: rgba(255, 255, 255, 0.1);
|
84 |
+
border-color: rgba(255, 255, 255, 0.4);
|
85 |
+
}
|
86 |
+
|
87 |
+
/* Search Bar Styles */
|
88 |
+
.search-container {
|
89 |
+
margin-left: 0.5rem;
|
90 |
+
}
|
91 |
+
|
92 |
+
.search-bar {
|
93 |
+
position: relative;
|
94 |
+
display: flex;
|
95 |
+
align-items: center;
|
96 |
+
background: rgba(0, 0, 0, 0.3);
|
97 |
+
border: 1px solid rgba(255, 255, 255, 0.2);
|
98 |
+
border-radius: 25px;
|
99 |
+
padding: 0.5rem 1rem;
|
100 |
+
min-width: 300px;
|
101 |
+
transition: all 0.3s ease;
|
102 |
+
}
|
103 |
+
|
104 |
+
.search-bar:focus-within {
|
105 |
+
background: rgba(0, 0, 0, 0.4);
|
106 |
+
border-color: rgba(59, 130, 246, 0.5);
|
107 |
+
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
|
108 |
+
}
|
109 |
+
|
110 |
+
.search-icon {
|
111 |
+
color: rgba(255, 255, 255, 0.6);
|
112 |
+
margin-right: 0.75rem;
|
113 |
+
font-size: 0.9rem;
|
114 |
+
}
|
115 |
+
|
116 |
+
.search-input {
|
117 |
+
background: transparent;
|
118 |
+
border: none;
|
119 |
+
color: var(--text);
|
120 |
+
font-size: 0.9rem;
|
121 |
+
font-weight: 500;
|
122 |
+
width: 100%;
|
123 |
+
outline: none;
|
124 |
+
}
|
125 |
+
|
126 |
+
.search-input::placeholder {
|
127 |
+
color: rgba(255, 255, 255, 0.5);
|
128 |
+
}
|
129 |
+
|
130 |
+
/* Dropdown Menu Styles */
|
131 |
+
.dropdown {
|
132 |
+
position: relative;
|
133 |
+
}
|
134 |
+
|
135 |
+
.dropdown-toggle {
|
136 |
+
display: flex;
|
137 |
+
align-items: center;
|
138 |
+
gap: 0.5rem;
|
139 |
+
}
|
140 |
+
|
141 |
+
.dropdown-toggle i {
|
142 |
+
font-size: 0.8rem;
|
143 |
+
transition: transform 0.2s ease;
|
144 |
+
}
|
145 |
+
|
146 |
+
.dropdown.active .dropdown-toggle i {
|
147 |
+
transform: rotate(180deg);
|
148 |
+
}
|
149 |
+
|
150 |
+
.dropdown-menu {
|
151 |
+
position: absolute;
|
152 |
+
top: 100%;
|
153 |
+
left: 50%;
|
154 |
+
transform: translateX(-50%);
|
155 |
+
background: rgba(15, 23, 42, 0.95);
|
156 |
+
border: 1px solid rgba(255, 255, 255, 0.1);
|
157 |
+
border-radius: 12px;
|
158 |
+
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
|
159 |
+
min-width: 500px;
|
160 |
+
opacity: 0;
|
161 |
+
visibility: hidden;
|
162 |
+
transition: all 0.3s ease;
|
163 |
+
z-index: 1000;
|
164 |
+
margin-top: 1rem;
|
165 |
+
-webkit-backdrop-filter: blur(10px);
|
166 |
+
backdrop-filter: blur(10px);
|
167 |
+
}
|
168 |
+
|
169 |
+
.dropdown.active .dropdown-menu {
|
170 |
+
opacity: 1;
|
171 |
+
visibility: visible;
|
172 |
+
}
|
173 |
+
|
174 |
+
.dropdown-content {
|
175 |
+
display: flex;
|
176 |
+
padding: 2rem;
|
177 |
+
}
|
178 |
+
|
179 |
+
.dropdown-section {
|
180 |
+
flex: 1;
|
181 |
+
}
|
182 |
+
|
183 |
+
.dropdown-section h4 {
|
184 |
+
color: #e2e8f0;
|
185 |
+
font-size: 0.875rem;
|
186 |
+
font-weight: 600;
|
187 |
+
margin: 0 0 1rem 0;
|
188 |
+
text-transform: uppercase;
|
189 |
+
letter-spacing: 0.05em;
|
190 |
+
}
|
191 |
+
|
192 |
+
.dropdown-section ul {
|
193 |
+
list-style: none;
|
194 |
+
margin: 0;
|
195 |
+
padding: 0;
|
196 |
+
}
|
197 |
+
|
198 |
+
.dropdown-section li {
|
199 |
+
margin-bottom: 0.75rem;
|
200 |
+
}
|
201 |
+
|
202 |
+
.dropdown-section a {
|
203 |
+
display: flex;
|
204 |
+
align-items: center;
|
205 |
+
gap: 0.75rem;
|
206 |
+
color: #94a3b8;
|
207 |
+
text-decoration: none;
|
208 |
+
font-size: 0.875rem;
|
209 |
+
padding: 0.5rem;
|
210 |
+
border-radius: 8px;
|
211 |
+
transition: all 0.2s ease;
|
212 |
+
}
|
213 |
+
|
214 |
+
.dropdown-section a:hover {
|
215 |
+
background: rgba(255, 255, 255, 0.1);
|
216 |
+
color: #e2e8f0;
|
217 |
+
}
|
218 |
+
|
219 |
+
.dropdown-section i {
|
220 |
+
font-size: 1rem;
|
221 |
+
width: 20px;
|
222 |
+
text-align: center;
|
223 |
+
}
|
224 |
+
|
225 |
+
.dropdown-divider {
|
226 |
+
width: 1px;
|
227 |
+
background: rgba(255, 255, 255, 0.2);
|
228 |
+
margin: 0 1.5rem;
|
229 |
+
}
|
230 |
+
|
231 |
+
.all-categories {
|
232 |
+
color: #60a5fa !important;
|
233 |
+
font-weight: 600;
|
234 |
+
margin-top: 0.5rem;
|
235 |
+
display: inline-flex;
|
236 |
+
align-items: center;
|
237 |
+
gap: 0.25rem;
|
238 |
+
}
|
239 |
+
|
240 |
+
.all-categories:hover {
|
241 |
+
color: #93c5fd !important;
|
242 |
+
}
|
243 |
+
|
244 |
+
/* Mobile Navigation */
|
245 |
+
.nav-toggle {
|
246 |
+
display: none;
|
247 |
+
flex-direction: column;
|
248 |
+
cursor: pointer;
|
249 |
+
gap: 4px;
|
250 |
+
}
|
251 |
+
|
252 |
+
.nav-toggle span {
|
253 |
+
width: 25px;
|
254 |
+
height: 3px;
|
255 |
+
background: var(--text);
|
256 |
+
border-radius: 2px;
|
257 |
+
transition: all 0.3s ease;
|
258 |
+
}
|
259 |
+
|
260 |
+
@media (max-width: 768px) {
|
261 |
+
.nav-menu {
|
262 |
+
display: none;
|
263 |
+
}
|
264 |
+
|
265 |
+
.nav-menu.active {
|
266 |
+
display: flex;
|
267 |
+
flex-direction: column;
|
268 |
+
position: absolute;
|
269 |
+
top: 100%;
|
270 |
+
left: 0;
|
271 |
+
right: 0;
|
272 |
+
background: rgba(15, 23, 42, 0.95);
|
273 |
+
-webkit-backdrop-filter: blur(10px);
|
274 |
+
backdrop-filter: blur(10px);
|
275 |
+
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
276 |
+
padding: 1rem;
|
277 |
+
}
|
278 |
+
|
279 |
+
.nav-toggle {
|
280 |
+
display: flex;
|
281 |
+
}
|
282 |
+
|
283 |
+
.search-container {
|
284 |
+
display: none;
|
285 |
+
}
|
286 |
+
}
|
287 |
+
|
288 |
+
/* Blog Page Styles */
|
289 |
+
.blog-hero {
|
290 |
+
padding: 4rem 0 3rem;
|
291 |
+
text-align: center;
|
292 |
+
max-width: 800px;
|
293 |
+
margin: 0 auto;
|
294 |
+
}
|
295 |
+
.blog-hero h1 {
|
296 |
+
font-size: 3rem;
|
297 |
+
font-weight: 700;
|
298 |
+
margin-bottom: 1rem;
|
299 |
+
background: linear-gradient(135deg, #3b82f6, #6366f1);
|
300 |
+
-webkit-background-clip: text;
|
301 |
+
-webkit-text-fill-color: transparent;
|
302 |
+
background-clip: text;
|
303 |
+
}
|
304 |
+
.blog-hero p {
|
305 |
+
font-size: 1.25rem;
|
306 |
+
color: var(--muted);
|
307 |
+
line-height: 1.6;
|
308 |
+
margin-bottom: 2rem;
|
309 |
+
}
|
310 |
+
|
311 |
+
.blog-grid {
|
312 |
+
max-width: 1200px;
|
313 |
+
margin: 0 auto;
|
314 |
+
padding: 0 1rem 4rem;
|
315 |
+
display: grid;
|
316 |
+
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
|
317 |
+
gap: 2rem;
|
318 |
+
}
|
319 |
+
|
320 |
+
.blog-card {
|
321 |
+
background: rgba(255, 255, 255, 0.05);
|
322 |
+
border-radius: 16px;
|
323 |
+
overflow: hidden;
|
324 |
+
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
325 |
+
border: 1px solid rgba(255, 255, 255, 0.1);
|
326 |
+
}
|
327 |
+
.blog-card:hover {
|
328 |
+
transform: translateY(-8px);
|
329 |
+
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
|
330 |
+
}
|
331 |
+
|
332 |
+
.blog-card-image {
|
333 |
+
width: 100%;
|
334 |
+
height: 200px;
|
335 |
+
background-size: cover;
|
336 |
+
background-position: center;
|
337 |
+
position: relative;
|
338 |
+
}
|
339 |
+
|
340 |
+
.blog-card-content {
|
341 |
+
padding: 1.5rem;
|
342 |
+
}
|
343 |
+
|
344 |
+
.blog-card-title {
|
345 |
+
font-size: 1.25rem;
|
346 |
+
font-weight: 600;
|
347 |
+
margin-bottom: 0.5rem;
|
348 |
+
color: var(--text);
|
349 |
+
line-height: 1.4;
|
350 |
+
}
|
351 |
+
|
352 |
+
.blog-card-date {
|
353 |
+
color: var(--muted);
|
354 |
+
font-size: 0.875rem;
|
355 |
+
margin-bottom: 1rem;
|
356 |
+
}
|
357 |
+
|
358 |
+
.blog-card-link {
|
359 |
+
color: #8b5cf6;
|
360 |
+
text-decoration: none;
|
361 |
+
font-weight: 600;
|
362 |
+
font-size: 0.875rem;
|
363 |
+
text-transform: uppercase;
|
364 |
+
letter-spacing: 0.5px;
|
365 |
+
transition: color 0.3s ease;
|
366 |
+
}
|
367 |
+
.blog-card-link:hover {
|
368 |
+
color: #a78bfa;
|
369 |
+
}
|
370 |
+
|
371 |
+
.pagination {
|
372 |
+
display: flex;
|
373 |
+
justify-content: center;
|
374 |
+
align-items: center;
|
375 |
+
gap: 0.5rem;
|
376 |
+
margin: 3rem 0;
|
377 |
+
}
|
378 |
+
|
379 |
+
.pagination-btn {
|
380 |
+
background: rgba(255, 255, 255, 0.1);
|
381 |
+
border: 1px solid rgba(255, 255, 255, 0.2);
|
382 |
+
color: var(--text);
|
383 |
+
padding: 0.5rem 1rem;
|
384 |
+
border-radius: 8px;
|
385 |
+
text-decoration: none;
|
386 |
+
transition: all 0.3s ease;
|
387 |
+
}
|
388 |
+
.pagination-btn:hover {
|
389 |
+
background: var(--brand);
|
390 |
+
border-color: var(--brand);
|
391 |
+
}
|
392 |
+
.pagination-btn.active {
|
393 |
+
background: var(--brand);
|
394 |
+
border-color: var(--brand);
|
395 |
+
}
|
396 |
+
|
397 |
+
@media (max-width: 768px) {
|
398 |
+
.blog-hero h1 {
|
399 |
+
font-size: 2rem;
|
400 |
+
}
|
401 |
+
.blog-grid {
|
402 |
+
grid-template-columns: 1fr;
|
403 |
+
padding: 0 1rem 2rem;
|
404 |
+
}
|
405 |
+
}
|
406 |
+
</style>
|
407 |
+
</head>
|
408 |
+
<body>
|
409 |
+
<header class="header">
|
410 |
+
<nav class="nav">
|
411 |
+
<div class="nav-container">
|
412 |
+
<div class="nav-logo">
|
413 |
+
<i class="fas fa-book-open"></i>
|
414 |
+
<span>booknap</span>
|
415 |
+
</div>
|
416 |
+
<div class="search-container">
|
417 |
+
<div class="search-bar">
|
418 |
+
<i class="fas fa-search search-icon"></i>
|
419 |
+
<input type="text" placeholder="Find a book..." class="search-input">
|
420 |
+
</div>
|
421 |
+
</div>
|
422 |
+
<ul class="nav-menu">
|
423 |
+
<li><a href="books.html" class="nav-link">Home</a></li>
|
424 |
+
<li class="dropdown">
|
425 |
+
<a href="#" class="nav-link dropdown-toggle">Book Summaries <i class="fas fa-chevron-down"></i></a>
|
426 |
+
<div class="dropdown-menu">
|
427 |
+
<div class="dropdown-content">
|
428 |
+
<div class="dropdown-section">
|
429 |
+
<h4>Browse by type</h4>
|
430 |
+
<ul>
|
431 |
+
<li><a href="#"><i class="fas fa-book-open" style="color: #10b981;"></i> Text Summaries</a></li>
|
432 |
+
<li><a href="#"><i class="fas fa-headphones" style="color: #3b82f6;"></i> Audio Summaries</a></li>
|
433 |
+
<li><a href="#"><i class="fas fa-play-circle" style="color: #8b5cf6;"></i> Video Summaries</a></li>
|
434 |
+
<li><a href="#"><i class="fas fa-file-pdf" style="color: #f59e0b;"></i> PDF Downloads</a></li>
|
435 |
+
<li><a href="#"><i class="fas fa-mobile-alt" style="color: #06b6d4;"></i> Mobile App</a></li>
|
436 |
+
</ul>
|
437 |
+
</div>
|
438 |
+
<div class="dropdown-divider"></div>
|
439 |
+
<div class="dropdown-section">
|
440 |
+
<h4>Browse by topic</h4>
|
441 |
+
<ul>
|
442 |
+
<li><a href="#"><i class="fas fa-brain" style="color: #f59e0b;"></i> Psychology</a></li>
|
443 |
+
<li><a href="#"><i class="fas fa-chart-line" style="color: #10b981;"></i> Business</a></li>
|
444 |
+
<li><a href="#"><i class="fas fa-heart" style="color: #ef4444;"></i> Self-Help</a></li>
|
445 |
+
<li><a href="#"><i class="fas fa-graduation-cap" style="color: #8b5cf6;"></i> Education</a></li>
|
446 |
+
<li><a href="#"><i class="fas fa-lightbulb" style="color: #06b6d4;"></i> Innovation</a></li>
|
447 |
+
</ul>
|
448 |
+
<a href="#" class="all-categories">all categories <i class="fas fa-arrow-right"></i></a>
|
449 |
+
</div>
|
450 |
+
</div>
|
451 |
+
</div>
|
452 |
+
</li>
|
453 |
+
<li><a href="pricing.html" class="nav-link">Pricing</a></li>
|
454 |
+
<li><a href="blog.html" class="nav-link active">Blog</a></li>
|
455 |
+
</ul>
|
456 |
+
<div class="nav-login">
|
457 |
+
<a href="login.html" class="login-btn">Login</a>
|
458 |
+
<a href="signup.html" class="signup-btn">Sign Up</a>
|
459 |
+
</div>
|
460 |
+
<div class="nav-toggle">
|
461 |
+
<span></span>
|
462 |
+
<span></span>
|
463 |
+
<span></span>
|
464 |
+
</div>
|
465 |
+
</div>
|
466 |
+
</nav>
|
467 |
+
</header>
|
468 |
+
|
469 |
+
<main>
|
470 |
+
<section class="blog-hero">
|
471 |
+
<h1>Read Our Blog</h1>
|
472 |
+
<p>Weekly articles with insights into the latest book summaries and reading strategies. Our blog takes the key concepts from popular books and lays out practical next steps, so you can learn and apply knowledge in meaningful ways.</p>
|
473 |
+
</section>
|
474 |
+
|
475 |
+
<div class="blog-grid">
|
476 |
+
<!-- Blog Card 1 -->
|
477 |
+
<article class="blog-card">
|
478 |
+
<div class="blog-card-image" style="background-image: url('https://images.unsplash.com/photo-1506905925346-21bda4d32df4?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2070&q=80');"></div>
|
479 |
+
<div class="blog-card-content">
|
480 |
+
<h3 class="blog-card-title">How to Access Your Inner Strength Through Reading</h3>
|
481 |
+
<p class="blog-card-date">June 17, 2025</p>
|
482 |
+
<a href="#" class="blog-card-link">VIEW THESE RESOURCES</a>
|
483 |
+
</div>
|
484 |
+
</article>
|
485 |
+
|
486 |
+
<!-- Blog Card 2 -->
|
487 |
+
<article class="blog-card">
|
488 |
+
<div class="blog-card-image" style="background-image: url('https://images.unsplash.com/photo-1544716278-ca5e3f4abd8c?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1974&q=80');"></div>
|
489 |
+
<div class="blog-card-content">
|
490 |
+
<h3 class="blog-card-title">Meditation is the Key to a Flourishing Life</h3>
|
491 |
+
<p class="blog-card-date">June 11, 2025</p>
|
492 |
+
<a href="#" class="blog-card-link">VIEW THESE RESOURCES</a>
|
493 |
+
</div>
|
494 |
+
</article>
|
495 |
+
|
496 |
+
<!-- Blog Card 3 -->
|
497 |
+
<article class="blog-card">
|
498 |
+
<div class="blog-card-image" style="background-image: url('https://images.unsplash.com/photo-1573496359142-b8d87734a5a2?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1976&q=80');"></div>
|
499 |
+
<div class="blog-card-content">
|
500 |
+
<h3 class="blog-card-title">Women's Leadership in Literature Isn't Optional</h3>
|
501 |
+
<p class="blog-card-date">June 5, 2025</p>
|
502 |
+
<a href="#" class="blog-card-link">VIEW THESE RESOURCES</a>
|
503 |
+
</div>
|
504 |
+
</article>
|
505 |
+
|
506 |
+
<!-- Blog Card 4 -->
|
507 |
+
<article class="blog-card">
|
508 |
+
<div class="blog-card-image" style="background-image: url('https://images.unsplash.com/photo-1522202176988-66273c2fd55f?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2071&q=80');"></div>
|
509 |
+
<div class="blog-card-content">
|
510 |
+
<h3 class="blog-card-title">Modeling Success for the Next Generation</h3>
|
511 |
+
<p class="blog-card-date">May 14, 2025</p>
|
512 |
+
<a href="#" class="blog-card-link">VIEW THESE RESOURCES</a>
|
513 |
+
</div>
|
514 |
+
</article>
|
515 |
+
|
516 |
+
<!-- Blog Card 5 -->
|
517 |
+
<article class="blog-card">
|
518 |
+
<div class="blog-card-image" style="background-image: url('https://images.unsplash.com/photo-1554224155-6726b3ff858f?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2011&q=80');"></div>
|
519 |
+
<div class="blog-card-content">
|
520 |
+
<h3 class="blog-card-title">How to Honor Tradition and Innovation</h3>
|
521 |
+
<p class="blog-card-date">May 6, 2025</p>
|
522 |
+
<a href="#" class="blog-card-link">VIEW THESE RESOURCES</a>
|
523 |
+
</div>
|
524 |
+
</article>
|
525 |
+
|
526 |
+
<!-- Blog Card 6 -->
|
527 |
+
<article class="blog-card">
|
528 |
+
<div class="blog-card-image" style="background-image: url('https://images.unsplash.com/photo-1506905925346-21bda4d32df4?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2070&q=80');"></div>
|
529 |
+
<div class="blog-card-content">
|
530 |
+
<h3 class="blog-card-title">Slow Down to Hear Your Inner Voice</h3>
|
531 |
+
<p class="blog-card-date">April 30, 2025</p>
|
532 |
+
<a href="#" class="blog-card-link">VIEW THESE RESOURCES</a>
|
533 |
+
</div>
|
534 |
+
</article>
|
535 |
+
|
536 |
+
<!-- Blog Card 7 -->
|
537 |
+
<article class="blog-card">
|
538 |
+
<div class="blog-card-image" style="background-image: url('https://images.unsplash.com/photo-1544716278-ca5e3f4abd8c?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1974&q=80');"></div>
|
539 |
+
<div class="blog-card-content">
|
540 |
+
<h3 class="blog-card-title">You Are Under Construction</h3>
|
541 |
+
<p class="blog-card-date">June 10, 2024</p>
|
542 |
+
<a href="#" class="blog-card-link">VIEW THESE RESOURCES</a>
|
543 |
+
</div>
|
544 |
+
</article>
|
545 |
+
|
546 |
+
<!-- Blog Card 8 -->
|
547 |
+
<article class="blog-card">
|
548 |
+
<div class="blog-card-image" style="background-image: url('https://images.unsplash.com/photo-1573496359142-b8d87734a5a2?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1976&q=80');"></div>
|
549 |
+
<div class="blog-card-content">
|
550 |
+
<h3 class="blog-card-title">Knowledge at the Center</h3>
|
551 |
+
<p class="blog-card-date">June 3, 2024</p>
|
552 |
+
<a href="#" class="blog-card-link">VIEW THESE RESOURCES</a>
|
553 |
+
</div>
|
554 |
+
</article>
|
555 |
+
|
556 |
+
<!-- Blog Card 9 -->
|
557 |
+
<article class="blog-card">
|
558 |
+
<div class="blog-card-image" style="background-image: url('https://images.unsplash.com/photo-1522202176988-66273c2fd55f?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2071&q=80');"></div>
|
559 |
+
<div class="blog-card-content">
|
560 |
+
<h3 class="blog-card-title">Let's Grow Together</h3>
|
561 |
+
<p class="blog-card-date">May 27, 2024</p>
|
562 |
+
<a href="#" class="blog-card-link">VIEW THESE RESOURCES</a>
|
563 |
+
</div>
|
564 |
+
</article>
|
565 |
+
</div>
|
566 |
+
|
567 |
+
<!-- Pagination -->
|
568 |
+
<div class="pagination">
|
569 |
+
<a href="#" class="pagination-btn active">1</a>
|
570 |
+
<a href="#" class="pagination-btn">2</a>
|
571 |
+
<a href="#" class="pagination-btn">3</a>
|
572 |
+
<span style="color: var(--muted); margin: 0 0.5rem;">β¦</span>
|
573 |
+
<a href="#" class="pagination-btn">16</a>
|
574 |
+
<a href="#" class="pagination-btn">Next Β»</a>
|
575 |
+
</div>
|
576 |
+
</main>
|
577 |
+
|
578 |
+
<script>
|
579 |
+
// Simple navigation toggle for mobile
|
580 |
+
document.querySelector('.nav-toggle').addEventListener('click', function() {
|
581 |
+
document.querySelector('.nav-menu').classList.toggle('active');
|
582 |
+
});
|
583 |
+
|
584 |
+
// Dropdown click behavior
|
585 |
+
document.addEventListener('DOMContentLoaded', function() {
|
586 |
+
const dropdown = document.querySelector('.dropdown');
|
587 |
+
const dropdownToggle = document.querySelector('.dropdown-toggle');
|
588 |
+
|
589 |
+
if (dropdown && dropdownToggle) {
|
590 |
+
dropdownToggle.addEventListener('click', function(e) {
|
591 |
+
e.preventDefault();
|
592 |
+
dropdown.classList.toggle('active');
|
593 |
+
});
|
594 |
+
|
595 |
+
// Close dropdown when clicking outside
|
596 |
+
document.addEventListener('click', function(e) {
|
597 |
+
if (!dropdown.contains(e.target)) {
|
598 |
+
dropdown.classList.remove('active');
|
599 |
+
}
|
600 |
+
});
|
601 |
+
|
602 |
+
// Close dropdown when pressing Escape key
|
603 |
+
document.addEventListener('keydown', function(e) {
|
604 |
+
if (e.key === 'Escape') {
|
605 |
+
dropdown.classList.remove('active');
|
606 |
+
}
|
607 |
+
});
|
608 |
+
}
|
609 |
+
});
|
610 |
+
</script>
|
611 |
+
</body>
|
612 |
+
</html>
|
booknap project/books.html
ADDED
@@ -0,0 +1,1072 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8" />
|
5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
6 |
+
<title>All Books - booknap</title>
|
7 |
+
<link rel="stylesheet" href="styles.css" />
|
8 |
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet" />
|
9 |
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" />
|
10 |
+
<style>
|
11 |
+
:root {
|
12 |
+
--bg: #0f172a;
|
13 |
+
--card: #0b1223;
|
14 |
+
--muted: #94a3b8;
|
15 |
+
--text: #e2e8f0;
|
16 |
+
--brand: #3b82f6;
|
17 |
+
--brand-2: #6366f1;
|
18 |
+
}
|
19 |
+
body {
|
20 |
+
background: linear-gradient(180deg, #0b1020, #0b1022 30%, #0b1124);
|
21 |
+
min-height: 100vh;
|
22 |
+
color: var(--text);
|
23 |
+
}
|
24 |
+
/* Match pricing header/nav styling */
|
25 |
+
.header { position: sticky; top: 0; -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px); background: rgba(7,10,20,0.55); z-index: 20; box-shadow: none; }
|
26 |
+
.nav { border-bottom: 1px solid rgba(255,255,255,0.06); }
|
27 |
+
.nav-logo i { color: var(--brand); }
|
28 |
+
.nav-link { color: var(--muted); text-decoration: none; font-weight: 600; }
|
29 |
+
.nav-link:hover, .nav-link.active { color: var(--text); }
|
30 |
+
.login-btn { background: var(--brand); color: white; padding: 0.6rem 1.1rem; border-radius: 9px; text-decoration: none; font-weight: 700; display: inline-block; }
|
31 |
+
|
32 |
+
/* Improved Navigation Layout */
|
33 |
+
.nav-container {
|
34 |
+
max-width: 1200px;
|
35 |
+
margin: 0 auto;
|
36 |
+
padding: 0 20px;
|
37 |
+
display: flex;
|
38 |
+
align-items: center;
|
39 |
+
gap: 2rem;
|
40 |
+
}
|
41 |
+
|
42 |
+
.nav-logo {
|
43 |
+
display: flex;
|
44 |
+
align-items: center;
|
45 |
+
gap: 0.5rem;
|
46 |
+
font-size: 1.5rem;
|
47 |
+
font-weight: 700;
|
48 |
+
color: white;
|
49 |
+
flex-shrink: 0;
|
50 |
+
}
|
51 |
+
|
52 |
+
.nav-logo i {
|
53 |
+
color: var(--brand);
|
54 |
+
font-size: 1.8rem;
|
55 |
+
}
|
56 |
+
|
57 |
+
.nav-menu {
|
58 |
+
display: flex;
|
59 |
+
align-items: center;
|
60 |
+
gap: 2rem;
|
61 |
+
list-style: none;
|
62 |
+
margin: 0;
|
63 |
+
padding: 0;
|
64 |
+
flex: 1;
|
65 |
+
justify-content: center;
|
66 |
+
}
|
67 |
+
|
68 |
+
.nav-link {
|
69 |
+
color: var(--muted);
|
70 |
+
text-decoration: none;
|
71 |
+
font-weight: 600;
|
72 |
+
font-size: 0.95rem;
|
73 |
+
transition: color 0.2s ease;
|
74 |
+
padding: 0.5rem 0;
|
75 |
+
}
|
76 |
+
|
77 |
+
.nav-link:hover, .nav-link.active {
|
78 |
+
color: var(--text);
|
79 |
+
}
|
80 |
+
|
81 |
+
.nav-login {
|
82 |
+
display: flex;
|
83 |
+
align-items: center;
|
84 |
+
gap: 1rem;
|
85 |
+
flex-shrink: 0;
|
86 |
+
}
|
87 |
+
/* Guide Right-Swiping Tabs */
|
88 |
+
.guide-tabs-section {
|
89 |
+
padding: 2rem 0 5rem;
|
90 |
+
}
|
91 |
+
.guide-tabs-container {
|
92 |
+
max-width: 1200px;
|
93 |
+
margin: 0 auto;
|
94 |
+
padding: 0 10px;
|
95 |
+
display: flex;
|
96 |
+
flex-direction: column;
|
97 |
+
}
|
98 |
+
.guide-tabs-panels {
|
99 |
+
order: 1;
|
100 |
+
}
|
101 |
+
.guide-tabs-nav {
|
102 |
+
order: 2;
|
103 |
+
display: flex;
|
104 |
+
justify-content: center;
|
105 |
+
background: rgba(255, 255, 255, 0.1);
|
106 |
+
border-radius: 16px;
|
107 |
+
padding: 0.3rem;
|
108 |
+
box-shadow: 0 8px 24px rgba(0,0,0,0.08);
|
109 |
+
position: relative;
|
110 |
+
overflow: hidden;
|
111 |
+
margin: 2rem auto 0 auto;
|
112 |
+
gap: 0.25rem;
|
113 |
+
width: fit-content;
|
114 |
+
-webkit-backdrop-filter: blur(10px);
|
115 |
+
backdrop-filter: blur(10px);
|
116 |
+
}
|
117 |
+
.guide-tab-btn {
|
118 |
+
background: transparent;
|
119 |
+
border: 0;
|
120 |
+
padding: 0.75rem 1.25rem;
|
121 |
+
border-radius: 16px;
|
122 |
+
font-weight: 600;
|
123 |
+
color: rgba(255, 255, 255, 0.8);
|
124 |
+
cursor: pointer;
|
125 |
+
position: relative;
|
126 |
+
z-index: 2;
|
127 |
+
transition: color 0.25s ease;
|
128 |
+
white-space: nowrap;
|
129 |
+
}
|
130 |
+
.guide-tab-btn.active { color: #ffffff; }
|
131 |
+
.guide-tab-slider {
|
132 |
+
position: absolute;
|
133 |
+
top: 0.4rem;
|
134 |
+
left: 0.4rem;
|
135 |
+
height: calc(100% - 0.8rem);
|
136 |
+
border-radius: 16px;
|
137 |
+
background: linear-gradient(90deg, #3b82f6, #6366f1);
|
138 |
+
box-shadow: 0 8px 24px rgba(59, 130, 246, 0.35);
|
139 |
+
transition: all 320ms cubic-bezier(0.4, 0, 0.2, 1);
|
140 |
+
z-index: 1;
|
141 |
+
width: 0;
|
142 |
+
}
|
143 |
+
|
144 |
+
.guide-tabs-panels { position: relative; }
|
145 |
+
.guide-tab-panel { display: none; }
|
146 |
+
.guide-tab-panel.active { display: block; }
|
147 |
+
|
148 |
+
.guide-card {
|
149 |
+
display: grid;
|
150 |
+
grid-template-columns: 1.25fr 1fr;
|
151 |
+
gap: 0;
|
152 |
+
border-radius: 16px;
|
153 |
+
overflow: hidden;
|
154 |
+
background: rgba(255, 255, 255, 0.1);
|
155 |
+
box-shadow: 0 16px 40px rgba(0,0,0,0.12);
|
156 |
+
-webkit-backdrop-filter: blur(10px);
|
157 |
+
backdrop-filter: blur(10px);
|
158 |
+
}
|
159 |
+
.guide-info {
|
160 |
+
background: linear-gradient(90deg, #3b82f6, #6366f1);
|
161 |
+
color: #ffffff;
|
162 |
+
padding: 2rem 2rem 2rem 2rem;
|
163 |
+
display: flex;
|
164 |
+
flex-direction: column;
|
165 |
+
justify-content: center;
|
166 |
+
height: 260px;
|
167 |
+
}
|
168 |
+
.guide-title {
|
169 |
+
font-size: 1.8rem;
|
170 |
+
font-weight: 800;
|
171 |
+
line-height: 1.2;
|
172 |
+
margin: 0 0 0.75rem 0;
|
173 |
+
}
|
174 |
+
.guide-text { opacity: 0.95; margin: 0 0 1.25rem 0; }
|
175 |
+
.guide-cta {
|
176 |
+
display: inline-flex;
|
177 |
+
align-items: center;
|
178 |
+
gap: 0.5rem;
|
179 |
+
color: #ffffff;
|
180 |
+
font-weight: 600;
|
181 |
+
text-decoration: none;
|
182 |
+
border-bottom: 2px solid rgba(255,255,255,0.45);
|
183 |
+
width: fit-content;
|
184 |
+
padding-bottom: 2px;
|
185 |
+
}
|
186 |
+
.guide-cta i { transition: transform 0.2s ease; }
|
187 |
+
.guide-cta:hover i { transform: translateX(3px); }
|
188 |
+
|
189 |
+
.guide-image { position: relative; background: rgba(255, 255, 255, 0.1); height: 260px; }
|
190 |
+
.guide-image img {
|
191 |
+
width: 100%; height: 100%; object-fit: cover;
|
192 |
+
display: block;
|
193 |
+
}
|
194 |
+
/* Nudge Shakespeare image so face is more centered/visible */
|
195 |
+
#guide-shakespeare .guide-image img { object-position: 10% 25%; }
|
196 |
+
/* Nudge Jane Austen image so face is more centered/visible */
|
197 |
+
#guide-austen .guide-image img { object-position: 10% 20%; }
|
198 |
+
/* Nudge Charles Dickens image so face is more centered/visible */
|
199 |
+
#guide-dickens .guide-image img { object-position: 40% 25%; }
|
200 |
+
|
201 |
+
@media (max-width: 900px) {
|
202 |
+
.guide-card { grid-template-columns: 1fr; }
|
203 |
+
.guide-image { order: -1; }
|
204 |
+
}
|
205 |
+
|
206 |
+
/* Navigation Login Button */
|
207 |
+
.nav-container {
|
208 |
+
display: flex;
|
209 |
+
align-items: center;
|
210 |
+
gap: 2rem;
|
211 |
+
}
|
212 |
+
|
213 |
+
.nav-menu {
|
214 |
+
display: flex;
|
215 |
+
align-items: center;
|
216 |
+
gap: 2rem;
|
217 |
+
margin-left: auto;
|
218 |
+
}
|
219 |
+
|
220 |
+
.nav-login {
|
221 |
+
margin-left: 0;
|
222 |
+
}
|
223 |
+
|
224 |
+
.login-btn {
|
225 |
+
background: linear-gradient(90deg, #3b82f6, #6366f1);
|
226 |
+
color: white;
|
227 |
+
padding: 0.75rem 1.5rem;
|
228 |
+
border-radius: 8px;
|
229 |
+
text-decoration: none;
|
230 |
+
font-weight: 600;
|
231 |
+
transition: background-color 0.2s ease;
|
232 |
+
display: inline-block;
|
233 |
+
}
|
234 |
+
|
235 |
+
.login-btn:hover {
|
236 |
+
background: linear-gradient(90deg, #2563eb, #4f46e5);
|
237 |
+
}
|
238 |
+
|
239 |
+
.signup-btn {
|
240 |
+
background: transparent;
|
241 |
+
color: var(--text);
|
242 |
+
padding: 0.75rem 1.5rem;
|
243 |
+
border: 2px solid rgba(255, 255, 255, 0.2);
|
244 |
+
border-radius: 8px;
|
245 |
+
text-decoration: none;
|
246 |
+
font-weight: 600;
|
247 |
+
transition: all 0.2s ease;
|
248 |
+
display: inline-block;
|
249 |
+
margin-left: 0.5rem;
|
250 |
+
}
|
251 |
+
|
252 |
+
.signup-btn:hover {
|
253 |
+
background: rgba(255, 255, 255, 0.1);
|
254 |
+
border-color: rgba(255, 255, 255, 0.4);
|
255 |
+
}
|
256 |
+
|
257 |
+
/* Profile Picture Upload Styles */
|
258 |
+
.profile-upload {
|
259 |
+
position: relative;
|
260 |
+
margin-right: 1rem;
|
261 |
+
margin-left: 1.5rem;
|
262 |
+
display: inline-block;
|
263 |
+
}
|
264 |
+
|
265 |
+
.profile-avatar {
|
266 |
+
width: 40px;
|
267 |
+
height: 40px;
|
268 |
+
border-radius: 50%;
|
269 |
+
background: linear-gradient(135deg, #3b82f6, #8b5cf6);
|
270 |
+
border: 2px solid rgba(255, 255, 255, 0.2);
|
271 |
+
cursor: pointer;
|
272 |
+
display: flex;
|
273 |
+
align-items: center;
|
274 |
+
justify-content: center;
|
275 |
+
color: white;
|
276 |
+
font-weight: bold;
|
277 |
+
font-size: 16px;
|
278 |
+
transition: all 0.3s ease;
|
279 |
+
overflow: hidden;
|
280 |
+
}
|
281 |
+
|
282 |
+
.profile-avatar:hover {
|
283 |
+
border-color: rgba(255, 255, 255, 0.4);
|
284 |
+
transform: scale(1.05);
|
285 |
+
}
|
286 |
+
|
287 |
+
.profile-avatar img {
|
288 |
+
width: 100%;
|
289 |
+
height: 100%;
|
290 |
+
object-fit: cover;
|
291 |
+
border-radius: 50%;
|
292 |
+
}
|
293 |
+
|
294 |
+
.profile-upload input[type="file"] {
|
295 |
+
position: absolute;
|
296 |
+
opacity: 0;
|
297 |
+
width: 100%;
|
298 |
+
height: 100%;
|
299 |
+
cursor: pointer;
|
300 |
+
}
|
301 |
+
|
302 |
+
.profile-upload:hover .profile-avatar {
|
303 |
+
border-color: rgba(255, 255, 255, 0.4);
|
304 |
+
}
|
305 |
+
|
306 |
+
/* Search Bar Styles */
|
307 |
+
.search-container {
|
308 |
+
margin-left: 0.5rem;
|
309 |
+
flex: 1;
|
310 |
+
max-width: 400px;
|
311 |
+
margin: 0 2rem;
|
312 |
+
}
|
313 |
+
|
314 |
+
.search-bar {
|
315 |
+
position: relative;
|
316 |
+
display: flex;
|
317 |
+
align-items: center;
|
318 |
+
background: rgba(0, 0, 0, 0.3);
|
319 |
+
border: 1px solid rgba(255, 255, 255, 0.2);
|
320 |
+
border-radius: 25px;
|
321 |
+
padding: 0.5rem 1rem;
|
322 |
+
min-width: 300px;
|
323 |
+
transition: all 0.3s ease;
|
324 |
+
}
|
325 |
+
|
326 |
+
.search-bar:focus-within {
|
327 |
+
background: rgba(0, 0, 0, 0.4);
|
328 |
+
border-color: rgba(59, 130, 246, 0.5);
|
329 |
+
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
|
330 |
+
}
|
331 |
+
|
332 |
+
.search-icon {
|
333 |
+
color: rgba(255, 255, 255, 0.6);
|
334 |
+
margin-right: 0.75rem;
|
335 |
+
font-size: 0.9rem;
|
336 |
+
}
|
337 |
+
|
338 |
+
.search-input {
|
339 |
+
background: transparent;
|
340 |
+
border: none;
|
341 |
+
color: var(--text);
|
342 |
+
font-size: 0.9rem;
|
343 |
+
font-weight: 500;
|
344 |
+
width: 100%;
|
345 |
+
outline: none;
|
346 |
+
}
|
347 |
+
|
348 |
+
.search-input::placeholder {
|
349 |
+
color: rgba(255, 255, 255, 0.5);
|
350 |
+
}
|
351 |
+
|
352 |
+
.search-input:focus::placeholder {
|
353 |
+
color: rgba(255, 255, 255, 0.3);
|
354 |
+
}
|
355 |
+
|
356 |
+
/* Responsive Navigation */
|
357 |
+
@media (max-width: 1024px) {
|
358 |
+
.nav-container {
|
359 |
+
gap: 1rem;
|
360 |
+
}
|
361 |
+
|
362 |
+
.nav-menu {
|
363 |
+
gap: 1.5rem;
|
364 |
+
}
|
365 |
+
|
366 |
+
.search-container {
|
367 |
+
margin: 0 1rem;
|
368 |
+
max-width: 300px;
|
369 |
+
}
|
370 |
+
}
|
371 |
+
|
372 |
+
@media (max-width: 768px) {
|
373 |
+
.nav-container {
|
374 |
+
flex-wrap: wrap;
|
375 |
+
gap: 1rem;
|
376 |
+
}
|
377 |
+
|
378 |
+
.nav-menu {
|
379 |
+
order: 3;
|
380 |
+
width: 100%;
|
381 |
+
justify-content: center;
|
382 |
+
gap: 1rem;
|
383 |
+
margin-top: 1rem;
|
384 |
+
}
|
385 |
+
|
386 |
+
.search-container {
|
387 |
+
order: 2;
|
388 |
+
margin: 0;
|
389 |
+
max-width: 100%;
|
390 |
+
flex: 1;
|
391 |
+
}
|
392 |
+
|
393 |
+
.nav-login {
|
394 |
+
order: 1;
|
395 |
+
margin-left: auto;
|
396 |
+
}
|
397 |
+
|
398 |
+
.search-bar {
|
399 |
+
min-width: 200px;
|
400 |
+
}
|
401 |
+
}
|
402 |
+
|
403 |
+
@media (max-width: 600px) {
|
404 |
+
.nav-container {
|
405 |
+
padding: 0 15px;
|
406 |
+
}
|
407 |
+
|
408 |
+
.nav-menu {
|
409 |
+
gap: 0.75rem;
|
410 |
+
font-size: 0.9rem;
|
411 |
+
}
|
412 |
+
|
413 |
+
.search-container {
|
414 |
+
margin: 0;
|
415 |
+
}
|
416 |
+
|
417 |
+
.search-bar {
|
418 |
+
min-width: 150px;
|
419 |
+
padding: 0.4rem 0.8rem;
|
420 |
+
}
|
421 |
+
|
422 |
+
.nav-login {
|
423 |
+
gap: 0.75rem;
|
424 |
+
}
|
425 |
+
|
426 |
+
.profile-avatar {
|
427 |
+
width: 35px;
|
428 |
+
height: 35px;
|
429 |
+
font-size: 14px;
|
430 |
+
}
|
431 |
+
|
432 |
+
.login-btn, .signup-btn {
|
433 |
+
padding: 0.5rem 1rem;
|
434 |
+
font-size: 0.9rem;
|
435 |
+
}
|
436 |
+
}
|
437 |
+
|
438 |
+
/* Community Section (homepage hero under header) */
|
439 |
+
.community-section { background: transparent; padding: 4rem 0; margin-top: 0; }
|
440 |
+
.community-container {
|
441 |
+
max-width: 1200px;
|
442 |
+
margin: 0 auto;
|
443 |
+
padding: 0 20px;
|
444 |
+
display: grid;
|
445 |
+
grid-template-columns: 1fr 1fr;
|
446 |
+
gap: 4rem;
|
447 |
+
align-items: center;
|
448 |
+
}
|
449 |
+
.community-content { color: var(--text); }
|
450 |
+
.community-title { font-size: 3.5rem; font-weight: 800; line-height: 1.1; margin-bottom: 1.5rem; color: var(--text); }
|
451 |
+
.community-description { font-size: 1.125rem; line-height: 1.7; color: var(--muted); margin-bottom: 0; }
|
452 |
+
.community-image-wrap { display: flex; align-items: center; justify-content: center; min-height: 220px; }
|
453 |
+
.community-image { width: 100%; max-width: 380px; height: auto; border-radius: 12px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.08); object-fit: contain; display: block; }
|
454 |
+
|
455 |
+
@media (max-width: 768px) {
|
456 |
+
.community-container { grid-template-columns: 1fr; gap: 2rem; }
|
457 |
+
.community-title { font-size: 2.5rem; }
|
458 |
+
}
|
459 |
+
|
460 |
+
/* Dropdown Menu Styles */
|
461 |
+
.dropdown {
|
462 |
+
position: relative;
|
463 |
+
}
|
464 |
+
|
465 |
+
.dropdown-toggle {
|
466 |
+
display: flex;
|
467 |
+
align-items: center;
|
468 |
+
gap: 0.5rem;
|
469 |
+
}
|
470 |
+
|
471 |
+
.dropdown-toggle i {
|
472 |
+
font-size: 0.8rem;
|
473 |
+
transition: transform 0.2s ease;
|
474 |
+
}
|
475 |
+
|
476 |
+
.dropdown.active .dropdown-toggle i {
|
477 |
+
transform: rotate(180deg);
|
478 |
+
}
|
479 |
+
|
480 |
+
.dropdown-menu {
|
481 |
+
position: absolute;
|
482 |
+
top: 100%;
|
483 |
+
left: 50%;
|
484 |
+
transform: translateX(-50%);
|
485 |
+
background: rgba(15, 23, 42, 0.95);
|
486 |
+
border: 1px solid rgba(255, 255, 255, 0.1);
|
487 |
+
border-radius: 12px;
|
488 |
+
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
|
489 |
+
min-width: 500px;
|
490 |
+
opacity: 0;
|
491 |
+
visibility: hidden;
|
492 |
+
transition: all 0.3s ease;
|
493 |
+
z-index: 1000;
|
494 |
+
margin-top: 1rem;
|
495 |
+
-webkit-backdrop-filter: blur(10px);
|
496 |
+
backdrop-filter: blur(10px);
|
497 |
+
}
|
498 |
+
|
499 |
+
.dropdown.active .dropdown-menu {
|
500 |
+
opacity: 1;
|
501 |
+
visibility: visible;
|
502 |
+
}
|
503 |
+
|
504 |
+
.dropdown-content {
|
505 |
+
display: flex;
|
506 |
+
padding: 2rem;
|
507 |
+
}
|
508 |
+
|
509 |
+
.dropdown-section {
|
510 |
+
flex: 1;
|
511 |
+
}
|
512 |
+
|
513 |
+
.dropdown-section h4 {
|
514 |
+
color: #e2e8f0;
|
515 |
+
font-size: 0.875rem;
|
516 |
+
font-weight: 600;
|
517 |
+
margin: 0 0 1rem 0;
|
518 |
+
text-transform: uppercase;
|
519 |
+
letter-spacing: 0.05em;
|
520 |
+
}
|
521 |
+
|
522 |
+
.dropdown-section ul {
|
523 |
+
list-style: none;
|
524 |
+
margin: 0;
|
525 |
+
padding: 0;
|
526 |
+
}
|
527 |
+
|
528 |
+
.dropdown-section li {
|
529 |
+
margin-bottom: 0.75rem;
|
530 |
+
}
|
531 |
+
|
532 |
+
.dropdown-section a {
|
533 |
+
display: flex;
|
534 |
+
align-items: center;
|
535 |
+
gap: 0.75rem;
|
536 |
+
color: #94a3b8;
|
537 |
+
text-decoration: none;
|
538 |
+
font-size: 0.875rem;
|
539 |
+
padding: 0.5rem;
|
540 |
+
border-radius: 8px;
|
541 |
+
transition: all 0.2s ease;
|
542 |
+
}
|
543 |
+
|
544 |
+
.dropdown-section a:hover {
|
545 |
+
background: rgba(255, 255, 255, 0.1);
|
546 |
+
color: #e2e8f0;
|
547 |
+
}
|
548 |
+
|
549 |
+
.dropdown-section i {
|
550 |
+
font-size: 1rem;
|
551 |
+
width: 20px;
|
552 |
+
text-align: center;
|
553 |
+
}
|
554 |
+
|
555 |
+
.dropdown-divider {
|
556 |
+
width: 1px;
|
557 |
+
background: rgba(255, 255, 255, 0.2);
|
558 |
+
margin: 0 1.5rem;
|
559 |
+
}
|
560 |
+
|
561 |
+
.all-categories {
|
562 |
+
color: #60a5fa !important;
|
563 |
+
font-weight: 500;
|
564 |
+
margin-top: 1rem;
|
565 |
+
display: inline-flex;
|
566 |
+
align-items: center;
|
567 |
+
gap: 0.5rem;
|
568 |
+
}
|
569 |
+
|
570 |
+
.all-categories:hover {
|
571 |
+
background: rgba(59, 130, 246, 0.2) !important;
|
572 |
+
color: #93c5fd !important;
|
573 |
+
}
|
574 |
+
|
575 |
+
.all-categories i {
|
576 |
+
font-size: 0.75rem;
|
577 |
+
transition: transform 0.2s ease;
|
578 |
+
}
|
579 |
+
|
580 |
+
.all-categories:hover i {
|
581 |
+
transform: translateX(3px);
|
582 |
+
}
|
583 |
+
|
584 |
+
/* Books Grid Section */
|
585 |
+
.books-grid-section {
|
586 |
+
padding: 4rem 0;
|
587 |
+
background: linear-gradient(135deg, #0b1020, #0b1022 30%, #0b1124);
|
588 |
+
}
|
589 |
+
|
590 |
+
.books-grid {
|
591 |
+
display: grid;
|
592 |
+
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
593 |
+
gap: 2rem;
|
594 |
+
margin-top: 2rem;
|
595 |
+
}
|
596 |
+
|
597 |
+
.book-card {
|
598 |
+
background: rgba(255, 255, 255, 0.1);
|
599 |
+
border-radius: 15px;
|
600 |
+
overflow: hidden;
|
601 |
+
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
|
602 |
+
transition: all 0.3s ease;
|
603 |
+
cursor: pointer;
|
604 |
+
-webkit-backdrop-filter: blur(10px);
|
605 |
+
backdrop-filter: blur(10px);
|
606 |
+
}
|
607 |
+
|
608 |
+
.book-card:hover {
|
609 |
+
transform: translateY(-10px);
|
610 |
+
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
|
611 |
+
background: rgba(255, 255, 255, 0.15);
|
612 |
+
}
|
613 |
+
|
614 |
+
.book-cover {
|
615 |
+
position: relative;
|
616 |
+
height: 200px;
|
617 |
+
overflow: hidden;
|
618 |
+
}
|
619 |
+
|
620 |
+
.book-cover img {
|
621 |
+
width: 100%;
|
622 |
+
height: 100%;
|
623 |
+
object-fit: cover;
|
624 |
+
transition: transform 0.3s ease;
|
625 |
+
}
|
626 |
+
|
627 |
+
.book-card:hover .book-cover img {
|
628 |
+
transform: scale(1.05);
|
629 |
+
}
|
630 |
+
|
631 |
+
.book-overlay {
|
632 |
+
position: absolute;
|
633 |
+
top: 0;
|
634 |
+
left: 0;
|
635 |
+
right: 0;
|
636 |
+
bottom: 0;
|
637 |
+
background: rgba(59, 130, 246, 0.8);
|
638 |
+
display: flex;
|
639 |
+
align-items: center;
|
640 |
+
justify-content: center;
|
641 |
+
opacity: 0;
|
642 |
+
transition: opacity 0.3s ease;
|
643 |
+
}
|
644 |
+
|
645 |
+
.book-overlay i {
|
646 |
+
color: white;
|
647 |
+
font-size: 2rem;
|
648 |
+
}
|
649 |
+
|
650 |
+
.book-card:hover .book-overlay {
|
651 |
+
opacity: 1;
|
652 |
+
}
|
653 |
+
|
654 |
+
.book-info {
|
655 |
+
padding: 1.5rem;
|
656 |
+
}
|
657 |
+
|
658 |
+
.book-info h3 {
|
659 |
+
font-size: 1.25rem;
|
660 |
+
font-weight: 600;
|
661 |
+
color: white;
|
662 |
+
margin-bottom: 0.5rem;
|
663 |
+
line-height: 1.3;
|
664 |
+
}
|
665 |
+
|
666 |
+
.book-info .book-author {
|
667 |
+
color: rgba(255, 255, 255, 0.8);
|
668 |
+
font-size: 0.875rem;
|
669 |
+
margin-bottom: 0.25rem;
|
670 |
+
}
|
671 |
+
|
672 |
+
.book-info .book-category {
|
673 |
+
background: rgba(255, 255, 255, 0.2);
|
674 |
+
color: white;
|
675 |
+
padding: 0.25rem 0.75rem;
|
676 |
+
border-radius: 15px;
|
677 |
+
font-size: 0.75rem;
|
678 |
+
font-weight: 600;
|
679 |
+
display: inline-block;
|
680 |
+
margin-bottom: 0.75rem;
|
681 |
+
}
|
682 |
+
|
683 |
+
.book-info .book-description {
|
684 |
+
color: rgba(255, 255, 255, 0.7);
|
685 |
+
font-size: 0.875rem;
|
686 |
+
line-height: 1.5;
|
687 |
+
}
|
688 |
+
|
689 |
+
/* Responsive navigation adjustments */
|
690 |
+
@media (max-width: 768px) {
|
691 |
+
.nav-login {
|
692 |
+
margin-left: 0;
|
693 |
+
margin-top: 1rem;
|
694 |
+
}
|
695 |
+
|
696 |
+
.dropdown-menu {
|
697 |
+
min-width: 300px;
|
698 |
+
left: 0;
|
699 |
+
transform: none;
|
700 |
+
}
|
701 |
+
|
702 |
+
.dropdown-content {
|
703 |
+
flex-direction: column;
|
704 |
+
padding: 1.5rem;
|
705 |
+
}
|
706 |
+
|
707 |
+
.dropdown-divider {
|
708 |
+
width: 100%;
|
709 |
+
height: 1px;
|
710 |
+
margin: 1rem 0;
|
711 |
+
}
|
712 |
+
|
713 |
+
.books-grid {
|
714 |
+
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
715 |
+
gap: 1.5rem;
|
716 |
+
}
|
717 |
+
}
|
718 |
+
</style>
|
719 |
+
</head>
|
720 |
+
<body>
|
721 |
+
<header class="header">
|
722 |
+
<nav class="nav">
|
723 |
+
<div class="nav-container">
|
724 |
+
<div class="nav-logo">
|
725 |
+
<i class="fas fa-book-open"></i>
|
726 |
+
<span>booknap</span>
|
727 |
+
</div>
|
728 |
+
<div class="search-container">
|
729 |
+
<div class="search-bar">
|
730 |
+
<i class="fas fa-search search-icon"></i>
|
731 |
+
<input type="text" placeholder="Find a book..." class="search-input">
|
732 |
+
</div>
|
733 |
+
</div>
|
734 |
+
<ul class="nav-menu">
|
735 |
+
<li><a href="books.html" class="nav-link active">Home</a></li>
|
736 |
+
<li class="dropdown">
|
737 |
+
<a href="#" class="nav-link dropdown-toggle">Book Summaries <i class="fas fa-chevron-down"></i></a>
|
738 |
+
<div class="dropdown-menu">
|
739 |
+
<div class="dropdown-content">
|
740 |
+
<div class="dropdown-section">
|
741 |
+
<h4>Browse by type</h4>
|
742 |
+
<ul>
|
743 |
+
<li><a href="#"><i class="fas fa-book-open" style="color: #10b981;"></i> Text Summaries</a></li>
|
744 |
+
<li><a href="#"><i class="fas fa-headphones" style="color: #3b82f6;"></i> Audio Summaries</a></li>
|
745 |
+
<li><a href="#"><i class="fas fa-play-circle" style="color: #8b5cf6;"></i> Video Summaries</a></li>
|
746 |
+
<li><a href="#"><i class="fas fa-file-pdf" style="color: #f59e0b;"></i> PDF Downloads</a></li>
|
747 |
+
<li><a href="#"><i class="fas fa-mobile-alt" style="color: #06b6d4;"></i> Mobile App</a></li>
|
748 |
+
</ul>
|
749 |
+
</div>
|
750 |
+
<div class="dropdown-divider"></div>
|
751 |
+
<div class="dropdown-section">
|
752 |
+
<h4>Browse by topic</h4>
|
753 |
+
<ul>
|
754 |
+
<li><a href="#"><i class="fas fa-brain" style="color: #f59e0b;"></i> Psychology</a></li>
|
755 |
+
<li><a href="#"><i class="fas fa-chart-line" style="color: #10b981;"></i> Business</a></li>
|
756 |
+
<li><a href="#"><i class="chevron-down"></i> Self-Help</a></li>
|
757 |
+
<li><a href="#"><i class="fas fa-graduation-cap" style="color: #8b5cf6;"></i> Education</a></li>
|
758 |
+
<li><a href="#"><i class="fas fa-lightbulb" style="color: #06b6d4;"></i> Innovation</a></li>
|
759 |
+
</ul>
|
760 |
+
<a href="#" class="all-categories">all categories <i class="fas fa-arrow-right"></i></a>
|
761 |
+
</div>
|
762 |
+
</div>
|
763 |
+
</div>
|
764 |
+
</li>
|
765 |
+
<li><a href="pricing.html" class="nav-link">Pricing</a></li>
|
766 |
+
<li><a href="blog.html" class="nav-link">Blog</a></li>
|
767 |
+
</ul>
|
768 |
+
<div class="nav-login">
|
769 |
+
<a href="login.html" class="login-btn">Login</a>
|
770 |
+
<a href="signup.html" class="signup-btn">Sign Up</a>
|
771 |
+
<div class="profile-upload">
|
772 |
+
<label for="profileInput" class="profile-avatar" id="profileAvatar" title="Click to upload profile picture">
|
773 |
+
<span>U</span>
|
774 |
+
</label>
|
775 |
+
<input type="file" id="profileInput" accept="image/*" onchange="updateProfilePicture(event)" aria-label="Upload profile picture">
|
776 |
+
</div>
|
777 |
+
</div>
|
778 |
+
<div class="nav-toggle">
|
779 |
+
<span></span>
|
780 |
+
<span></span>
|
781 |
+
<span></span>
|
782 |
+
</div>
|
783 |
+
</div>
|
784 |
+
</nav>
|
785 |
+
</header>
|
786 |
+
|
787 |
+
<main>
|
788 |
+
<!-- Community Section under header -->
|
789 |
+
<section class="community-section">
|
790 |
+
<div class="community-container">
|
791 |
+
<div class="community-content">
|
792 |
+
<h1 class="community-title">
|
793 |
+
Level up with the largest<br>
|
794 |
+
<span style="color: #3b82f6;">reading community</span>
|
795 |
+
</h1>
|
796 |
+
<p class="community-description">
|
797 |
+
Join book lovers to share insights, discuss ideas, and stay up-to-date on all the latest books and reading techniques.
|
798 |
+
</p>
|
799 |
+
</div>
|
800 |
+
<div class="community-image-wrap">
|
801 |
+
<img class="community-image" src="https://i.pinimg.com/736x/f4/a0/48/f4a0480397a1c019a2a1a238b2ffc594.jpg" alt="Reading illustration" />
|
802 |
+
</div>
|
803 |
+
</div>
|
804 |
+
</section>
|
805 |
+
|
806 |
+
|
807 |
+
<!-- Right-swiping tabs (matching screenshot layout) -->
|
808 |
+
<section class="guide-tabs-section">
|
809 |
+
<div class="guide-tabs-container">
|
810 |
+
<div class="guide-tabs-nav" role="tablist" aria-label="Author guides">
|
811 |
+
<div class="guide-tab-slider" aria-hidden="true"></div>
|
812 |
+
<button class="guide-tab-btn active" role="tab" aria-selected="true" aria-controls="guide-dickens" id="tab-dickens">Dickens</button>
|
813 |
+
<button class="guide-tab-btn" role="tab" aria-selected="false" aria-controls="guide-austen" id="tab-austen">Austen</button>
|
814 |
+
<button class="guide-tab-btn" role="tab" aria-selected="false" aria-controls="guide-shakespeare" id="tab-shakespeare">Shakespeare</button>
|
815 |
+
</div>
|
816 |
+
|
817 |
+
<div class="guide-tabs-panels">
|
818 |
+
<!-- Charles Dickens (now first) -->
|
819 |
+
<div class="guide-tab-panel active" id="guide-dickens" role="tabpanel" aria-labelledby="tab-dickens">
|
820 |
+
<div class="guide-card">
|
821 |
+
<div class="guide-info">
|
822 |
+
<h2 class="guide-title">Charles Dickens' London</h2>
|
823 |
+
<p class="guide-text">Walk the foggy streets of Victorian London and uncover the life and times that shaped Dickens' unforgettable characters.</p>
|
824 |
+
<a class="guide-cta" href="#"><span>Read the guide</span> <i class="fas fa-arrow-right"></i></a>
|
825 |
+
</div>
|
826 |
+
<div class="guide-image">
|
827 |
+
<img alt="Charles Dickens" src="https://www.historic-uk.com/wp-content/uploads/2019/06/dickens-in-study.jpg" />
|
828 |
+
</div>
|
829 |
+
</div>
|
830 |
+
</div>
|
831 |
+
|
832 |
+
<!-- Jane Austen (remains second) -->
|
833 |
+
<div class="guide-tab-panel" id="guide-austen" role="tabpanel" aria-labelledby="tab-austen">
|
834 |
+
<div class="guide-card">
|
835 |
+
<div class="guide-info">
|
836 |
+
<h2 class="guide-title">Jane Austen's World</h2>
|
837 |
+
<p class="guide-text">Explore the Regency era, societal norms, and the life behind the beloved novels. Perfect for essays and deeper reading.</p>
|
838 |
+
<a class="guide-cta" href="#"><span>Read the guide</span> <i class="fas fa-arrow-right"></i></a>
|
839 |
+
</div>
|
840 |
+
<div class="guide-image">
|
841 |
+
<img alt="Jane Austen" src="https://wordsworth-editions.com/wp-content/uploads/2022/02/jane-austen.jpg" />
|
842 |
+
</div>
|
843 |
+
</div>
|
844 |
+
</div>
|
845 |
+
|
846 |
+
<!-- William Shakespeare (now third) -->
|
847 |
+
<div class="guide-tab-panel" id="guide-shakespeare" role="tabpanel" aria-labelledby="tab-shakespeare">
|
848 |
+
<div class="guide-card">
|
849 |
+
<div class="guide-info">
|
850 |
+
<h2 class="guide-title">William Shakespeare's Life & Times</h2>
|
851 |
+
<p class="guide-text">Our comprehensive guide includes a detailed biography, social and historical context, quotes, and more to help you write your essay on Shakespeare or understand his plays and poems.</p>
|
852 |
+
<a class="guide-cta" href="#"><span>Read the guide</span> <i class="fas fa-arrow-right"></i></a>
|
853 |
+
</div>
|
854 |
+
<div class="guide-image">
|
855 |
+
<img alt="William Shakespeare" src="https://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Shakespeare.jpg/640px-Shakespeare.jpg" />
|
856 |
+
</div>
|
857 |
+
</div>
|
858 |
+
</div>
|
859 |
+
</div>
|
860 |
+
</div>
|
861 |
+
</section>
|
862 |
+
|
863 |
+
<section class="books-grid-section">
|
864 |
+
<div class="container">
|
865 |
+
<div class="books-grid">
|
866 |
+
<div class="book-card" onclick="window.location.href='book.html?id=1'">
|
867 |
+
<div class="book-cover">
|
868 |
+
<img src="assets/covers/atomic-habits.svg" alt="Atomic Habits" />
|
869 |
+
<div class="book-overlay"><i class="fas fa-play"></i></div>
|
870 |
+
</div>
|
871 |
+
<div class="book-info">
|
872 |
+
<h3>Atomic Habits</h3>
|
873 |
+
<p class="book-author">James Clear</p>
|
874 |
+
<p class="book-category">Self-Help</p>
|
875 |
+
<p class="book-description">Learn how tiny changes create remarkable results in your life.</p>
|
876 |
+
</div>
|
877 |
+
</div>
|
878 |
+
|
879 |
+
<div class="book-card" onclick="window.location.href='book.html?id=2'">
|
880 |
+
<div class="book-cover">
|
881 |
+
<img src="assets/covers/thinking-fast-slow.svg" alt="Thinking, Fast and Slow" />
|
882 |
+
<div class="book-overlay"><i class="fas fa-play"></i></div>
|
883 |
+
</div>
|
884 |
+
<div class="book-info">
|
885 |
+
<h3>Thinking, Fast and Slow</h3>
|
886 |
+
<p class="book-author">Daniel Kahneman</p>
|
887 |
+
<p class="book-category">Psychology</p>
|
888 |
+
<p class="book-description">Understanding the two systems that drive the way we think.</p>
|
889 |
+
</div>
|
890 |
+
</div>
|
891 |
+
|
892 |
+
<div class="book-card" onclick="window.location.href='book.html?id=3'">
|
893 |
+
<div class="book-cover">
|
894 |
+
<img src="assets/covers/7-habits.svg" alt="The 7 Habits of Highly Effective People" />
|
895 |
+
<div class="book-overlay"><i class="fas fa-play"></i></div>
|
896 |
+
</div>
|
897 |
+
<div class="book-info">
|
898 |
+
<h3>The 7 Habits of Highly Effective People</h3>
|
899 |
+
<p class="book-author">Stephen R. Covey</p>
|
900 |
+
<p class="book-category">Self-Help</p>
|
901 |
+
<p class="book-description">Powerful lessons in personal change and effectiveness.</p>
|
902 |
+
</div>
|
903 |
+
</div>
|
904 |
+
|
905 |
+
<div class="book-card" onclick="window.location.href='book.html?id=4'">
|
906 |
+
<div class="book-cover">
|
907 |
+
<img src="assets/covers/rich-dad-poor-dad.svg" alt="Rich Dad Poor Dad" />
|
908 |
+
<div class="book-overlay"><i class="fas fa-play"></i></div>
|
909 |
+
</div>
|
910 |
+
<div class="book-info">
|
911 |
+
<h3>Rich Dad Poor Dad</h3>
|
912 |
+
<p class="book-author">Robert T. Kiyosaki</p>
|
913 |
+
<p class="book-category">Finance</p>
|
914 |
+
<p class="book-description">What the rich teach their kids about money.</p>
|
915 |
+
</div>
|
916 |
+
</div>
|
917 |
+
|
918 |
+
<div class="book-card" onclick="window.location.href='book.html?id=5'">
|
919 |
+
<div class="book-cover">
|
920 |
+
<img src="assets/covers/zero-to-one.svg" alt="Zero to One" />
|
921 |
+
<div class="book-overlay"><i class="fas fa-play"></i></div>
|
922 |
+
</div>
|
923 |
+
<div class="book-info">
|
924 |
+
<h3>Zero to One</h3>
|
925 |
+
<p class="book-author">Peter Thiel</p>
|
926 |
+
<p class="book-category">Business</p>
|
927 |
+
<p class="book-description">Notes on startups, or how to build the future.</p>
|
928 |
+
</div>
|
929 |
+
</div>
|
930 |
+
|
931 |
+
<div class="book-card" onclick="window.location.href='book.html?id=6'">
|
932 |
+
<div class="book-cover">
|
933 |
+
<img src="assets/covers/start-with-why.svg" alt="Start With Why" />
|
934 |
+
<div class="book-overlay"><i class="fas fa-play"></i></div>
|
935 |
+
</div>
|
936 |
+
<div class="book-info">
|
937 |
+
<h3>Start With Why</h3>
|
938 |
+
<p class="book-author">Simon Sinek</p>
|
939 |
+
<p class="book-category">Leadership</p>
|
940 |
+
<p class="book-description">How great leaders inspire everyone to take action.</p>
|
941 |
+
</div>
|
942 |
+
</div>
|
943 |
+
</div>
|
944 |
+
</div>
|
945 |
+
</section>
|
946 |
+
</main>
|
947 |
+
|
948 |
+
<footer class="footer">
|
949 |
+
<div class="container">
|
950 |
+
<p>© 2024 booknap. All rights reserved.</p>
|
951 |
+
</div>
|
952 |
+
</footer>
|
953 |
+
|
954 |
+
<script src="script.js"></script>
|
955 |
+
<script>
|
956 |
+
// Dropdown click behavior
|
957 |
+
(function() {
|
958 |
+
const dropdown = document.querySelector('.dropdown');
|
959 |
+
const dropdownToggle = document.querySelector('.dropdown-toggle');
|
960 |
+
|
961 |
+
if (dropdown && dropdownToggle) {
|
962 |
+
dropdownToggle.addEventListener('click', function(e) {
|
963 |
+
e.preventDefault();
|
964 |
+
e.stopPropagation();
|
965 |
+
dropdown.classList.toggle('active');
|
966 |
+
});
|
967 |
+
|
968 |
+
// Close dropdown when clicking outside
|
969 |
+
document.addEventListener('click', function(e) {
|
970 |
+
if (!dropdown.contains(e.target)) {
|
971 |
+
dropdown.classList.remove('active');
|
972 |
+
}
|
973 |
+
});
|
974 |
+
|
975 |
+
// Close dropdown when pressing Escape key
|
976 |
+
document.addEventListener('keydown', function(e) {
|
977 |
+
if (e.key === 'Escape') {
|
978 |
+
dropdown.classList.remove('active');
|
979 |
+
}
|
980 |
+
});
|
981 |
+
}
|
982 |
+
})();
|
983 |
+
|
984 |
+
// Guide right-swiping tabs behavior
|
985 |
+
(function() {
|
986 |
+
const nav = document.querySelector('.guide-tabs-nav');
|
987 |
+
if (!nav) return;
|
988 |
+
const buttons = Array.from(nav.querySelectorAll('.guide-tab-btn'));
|
989 |
+
const slider = nav.querySelector('.guide-tab-slider');
|
990 |
+
const panels = Array.from(document.querySelectorAll('.guide-tab-panel'));
|
991 |
+
|
992 |
+
function activate(idx) {
|
993 |
+
buttons.forEach((b, i) => {
|
994 |
+
const isActive = i === idx;
|
995 |
+
b.classList.toggle('active', isActive);
|
996 |
+
b.setAttribute('aria-selected', String(isActive));
|
997 |
+
panels[i].classList.toggle('active', isActive);
|
998 |
+
});
|
999 |
+
const activeBtn = buttons[idx];
|
1000 |
+
if (activeBtn && slider) {
|
1001 |
+
slider.style.width = activeBtn.offsetWidth + 'px';
|
1002 |
+
slider.style.left = activeBtn.offsetLeft + 'px'; // swipe right visual
|
1003 |
+
}
|
1004 |
+
activeIndex = idx;
|
1005 |
+
}
|
1006 |
+
|
1007 |
+
let activeIndex = buttons.findIndex(b => b.classList.contains('active'));
|
1008 |
+
if (activeIndex < 0) activeIndex = 0;
|
1009 |
+
// init slider position after layout
|
1010 |
+
window.requestAnimationFrame(() => activate(activeIndex));
|
1011 |
+
|
1012 |
+
buttons.forEach((btn, i) => btn.addEventListener('click', () => activate(i)));
|
1013 |
+
|
1014 |
+
// Touch swipe support on the whole tabs section
|
1015 |
+
const swipeHost = document.querySelector('.guide-tabs-section');
|
1016 |
+
let touchStartX = 0;
|
1017 |
+
let touchEndX = 0;
|
1018 |
+
const threshold = 40; // px
|
1019 |
+
|
1020 |
+
function handleGesture() {
|
1021 |
+
const dx = touchEndX - touchStartX;
|
1022 |
+
if (Math.abs(dx) < threshold) return;
|
1023 |
+
if (dx < 0) {
|
1024 |
+
// swipe left -> next (slider moves right)
|
1025 |
+
activate(Math.min(activeIndex + 1, buttons.length - 1));
|
1026 |
+
} else {
|
1027 |
+
// swipe right -> prev
|
1028 |
+
activate(Math.max(activeIndex - 1, 0));
|
1029 |
+
}
|
1030 |
+
}
|
1031 |
+
|
1032 |
+
if (swipeHost) {
|
1033 |
+
swipeHost.addEventListener('touchstart', e => { touchStartX = e.changedTouches[0].clientX; }, { passive: true });
|
1034 |
+
swipeHost.addEventListener('touchend', e => { touchEndX = e.changedTouches[0].clientX; handleGesture(); }, { passive: true });
|
1035 |
+
}
|
1036 |
+
|
1037 |
+
// Reposition slider on resize
|
1038 |
+
window.addEventListener('resize', () => activate(activeIndex));
|
1039 |
+
})();
|
1040 |
+
|
1041 |
+
// Profile picture update function
|
1042 |
+
function updateProfilePicture(event) {
|
1043 |
+
const file = event.target.files[0];
|
1044 |
+
if (file) {
|
1045 |
+
if (file.type.startsWith('image/')) {
|
1046 |
+
const reader = new FileReader();
|
1047 |
+
reader.onload = function(e) {
|
1048 |
+
const profileAvatar = document.getElementById('profileAvatar');
|
1049 |
+
profileAvatar.innerHTML = `<img src="${e.target.result}" alt="Profile picture">`;
|
1050 |
+
|
1051 |
+
// Store in localStorage for persistence
|
1052 |
+
localStorage.setItem('profilePicture', e.target.result);
|
1053 |
+
};
|
1054 |
+
reader.readAsDataURL(file);
|
1055 |
+
} else {
|
1056 |
+
alert('Please select a valid image file.');
|
1057 |
+
}
|
1058 |
+
}
|
1059 |
+
}
|
1060 |
+
|
1061 |
+
// Load saved profile picture on page load
|
1062 |
+
document.addEventListener('DOMContentLoaded', function() {
|
1063 |
+
const savedPicture = localStorage.getItem('profilePicture');
|
1064 |
+
if (savedPicture) {
|
1065 |
+
const profileAvatar = document.getElementById('profileAvatar');
|
1066 |
+
profileAvatar.innerHTML = `<img src="${savedPicture}" alt="Profile picture">`;
|
1067 |
+
}
|
1068 |
+
});
|
1069 |
+
</script>
|
1070 |
+
</body>
|
1071 |
+
</html>
|
1072 |
+
|
booknap project/business-leaders.html
ADDED
@@ -0,0 +1,376 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8">
|
5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6 |
+
<title>Booknap - News & Business Wisdom</title>
|
7 |
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet" />
|
8 |
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" />
|
9 |
+
<style>
|
10 |
+
:root {
|
11 |
+
--bg: #0f172a;
|
12 |
+
--card: #0b1223;
|
13 |
+
--muted: #94a3b8;
|
14 |
+
--text: #e2e8f0;
|
15 |
+
--brand: #3b82f6;
|
16 |
+
--brand-2: #6366f1;
|
17 |
+
}
|
18 |
+
|
19 |
+
body {
|
20 |
+
font-family: 'Inter', sans-serif;
|
21 |
+
background: linear-gradient(180deg, #0b1020, #0b1022 30%, #0b1124);
|
22 |
+
color: var(--text);
|
23 |
+
margin: 0;
|
24 |
+
padding: 0;
|
25 |
+
}
|
26 |
+
|
27 |
+
.container {
|
28 |
+
max-width: 1200px;
|
29 |
+
margin: 0 auto;
|
30 |
+
padding: 20px;
|
31 |
+
}
|
32 |
+
|
33 |
+
.header {
|
34 |
+
text-align: center;
|
35 |
+
margin-bottom: 3rem;
|
36 |
+
}
|
37 |
+
|
38 |
+
.header h1 {
|
39 |
+
font-size: 3rem;
|
40 |
+
font-weight: 700;
|
41 |
+
margin-bottom: 1rem;
|
42 |
+
background: linear-gradient(135deg, #3b82f6, #6366f1);
|
43 |
+
-webkit-background-clip: text;
|
44 |
+
-webkit-text-fill-color: transparent;
|
45 |
+
background-clip: text;
|
46 |
+
}
|
47 |
+
|
48 |
+
.header p {
|
49 |
+
font-size: 1.25rem;
|
50 |
+
color: var(--muted);
|
51 |
+
line-height: 1.6;
|
52 |
+
}
|
53 |
+
|
54 |
+
/* Tab Navigation */
|
55 |
+
.tab-nav {
|
56 |
+
display: flex;
|
57 |
+
justify-content: center;
|
58 |
+
gap: 1rem;
|
59 |
+
margin-bottom: 3rem;
|
60 |
+
background: rgba(255, 255, 255, 0.05);
|
61 |
+
border-radius: 16px;
|
62 |
+
padding: 0.5rem;
|
63 |
+
max-width: 500px;
|
64 |
+
margin-left: auto;
|
65 |
+
margin-right: auto;
|
66 |
+
}
|
67 |
+
|
68 |
+
.tab-btn {
|
69 |
+
background: transparent;
|
70 |
+
border: none;
|
71 |
+
color: var(--muted);
|
72 |
+
padding: 0.75rem 1.5rem;
|
73 |
+
border-radius: 12px;
|
74 |
+
cursor: pointer;
|
75 |
+
font-weight: 600;
|
76 |
+
transition: all 0.3s ease;
|
77 |
+
flex: 1;
|
78 |
+
}
|
79 |
+
|
80 |
+
.tab-btn.active {
|
81 |
+
background: var(--brand);
|
82 |
+
color: white;
|
83 |
+
}
|
84 |
+
|
85 |
+
.tab-btn:hover:not(.active) {
|
86 |
+
color: var(--text);
|
87 |
+
}
|
88 |
+
|
89 |
+
/* Tab Content */
|
90 |
+
.tab-content {
|
91 |
+
display: none;
|
92 |
+
}
|
93 |
+
|
94 |
+
.tab-content.active {
|
95 |
+
display: block;
|
96 |
+
}
|
97 |
+
|
98 |
+
/* Grid Layout */
|
99 |
+
.grid {
|
100 |
+
display: grid;
|
101 |
+
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
|
102 |
+
gap: 2rem;
|
103 |
+
}
|
104 |
+
|
105 |
+
/* News Cards */
|
106 |
+
.news-card {
|
107 |
+
background: rgba(255, 255, 255, 0.05);
|
108 |
+
border-radius: 16px;
|
109 |
+
overflow: hidden;
|
110 |
+
border: 1px solid rgba(255, 255, 255, 0.1);
|
111 |
+
transition: transform 0.3s ease;
|
112 |
+
}
|
113 |
+
|
114 |
+
.news-card:hover {
|
115 |
+
transform: translateY(-8px);
|
116 |
+
}
|
117 |
+
|
118 |
+
.news-card-image {
|
119 |
+
width: 100%;
|
120 |
+
height: 200px;
|
121 |
+
background-size: cover;
|
122 |
+
background-position: center;
|
123 |
+
}
|
124 |
+
|
125 |
+
.news-card-content {
|
126 |
+
padding: 1.5rem;
|
127 |
+
}
|
128 |
+
|
129 |
+
.news-card-title {
|
130 |
+
font-size: 1.25rem;
|
131 |
+
font-weight: 600;
|
132 |
+
margin-bottom: 0.5rem;
|
133 |
+
}
|
134 |
+
|
135 |
+
.news-card-date {
|
136 |
+
color: var(--muted);
|
137 |
+
font-size: 0.875rem;
|
138 |
+
margin-bottom: 1rem;
|
139 |
+
}
|
140 |
+
|
141 |
+
/* Business Wisdom Cards */
|
142 |
+
.wisdom-card {
|
143 |
+
background: rgba(255, 255, 255, 0.05);
|
144 |
+
border-radius: 16px;
|
145 |
+
padding: 2rem;
|
146 |
+
border: 1px solid rgba(255, 255, 255, 0.1);
|
147 |
+
transition: transform 0.3s ease;
|
148 |
+
position: relative;
|
149 |
+
overflow: hidden;
|
150 |
+
}
|
151 |
+
|
152 |
+
.wisdom-card:hover {
|
153 |
+
transform: translateY(-8px);
|
154 |
+
}
|
155 |
+
|
156 |
+
.wisdom-card::before {
|
157 |
+
content: '"';
|
158 |
+
position: absolute;
|
159 |
+
top: 1rem;
|
160 |
+
left: 1.5rem;
|
161 |
+
font-size: 4rem;
|
162 |
+
color: var(--brand);
|
163 |
+
opacity: 0.3;
|
164 |
+
font-family: serif;
|
165 |
+
}
|
166 |
+
|
167 |
+
.wisdom-quote {
|
168 |
+
font-size: 1.1rem;
|
169 |
+
line-height: 1.6;
|
170 |
+
margin-bottom: 1.5rem;
|
171 |
+
font-style: italic;
|
172 |
+
color: var(--text);
|
173 |
+
}
|
174 |
+
|
175 |
+
.wisdom-author {
|
176 |
+
font-weight: 600;
|
177 |
+
color: var(--brand);
|
178 |
+
margin-bottom: 0.5rem;
|
179 |
+
}
|
180 |
+
|
181 |
+
.wisdom-meta {
|
182 |
+
color: var(--muted);
|
183 |
+
font-size: 0.875rem;
|
184 |
+
}
|
185 |
+
|
186 |
+
.loading {
|
187 |
+
text-align: center;
|
188 |
+
padding: 3rem;
|
189 |
+
color: var(--muted);
|
190 |
+
}
|
191 |
+
|
192 |
+
.error {
|
193 |
+
text-align: center;
|
194 |
+
padding: 3rem;
|
195 |
+
color: #ef4444;
|
196 |
+
}
|
197 |
+
|
198 |
+
/* Responsive */
|
199 |
+
@media (max-width: 768px) {
|
200 |
+
.header h1 {
|
201 |
+
font-size: 2rem;
|
202 |
+
}
|
203 |
+
|
204 |
+
.tab-nav {
|
205 |
+
flex-direction: column;
|
206 |
+
}
|
207 |
+
|
208 |
+
.grid {
|
209 |
+
grid-template-columns: 1fr;
|
210 |
+
}
|
211 |
+
}
|
212 |
+
</style>
|
213 |
+
</head>
|
214 |
+
<body>
|
215 |
+
<div class="container">
|
216 |
+
<div class="header">
|
217 |
+
<h1>News & Business Wisdom</h1>
|
218 |
+
<p>Stay informed with the latest news and inspired by wisdom from business leaders</p>
|
219 |
+
</div>
|
220 |
+
|
221 |
+
<!-- Tab Navigation -->
|
222 |
+
<div class="tab-nav">
|
223 |
+
<button class="tab-btn active" onclick="showTab('news')">
|
224 |
+
<i class="fas fa-newspaper"></i> Latest News
|
225 |
+
</button>
|
226 |
+
<button class="tab-btn" onclick="showTab('wisdom')">
|
227 |
+
<i class="fas fa-lightbulb"></i> Business Wisdom
|
228 |
+
</button>
|
229 |
+
</div>
|
230 |
+
|
231 |
+
<!-- News Tab -->
|
232 |
+
<div id="news-tab" class="tab-content active">
|
233 |
+
<div class="grid" id="news-grid">
|
234 |
+
<div class="loading">Loading news...</div>
|
235 |
+
</div>
|
236 |
+
</div>
|
237 |
+
|
238 |
+
<!-- Business Wisdom Tab -->
|
239 |
+
<div id="wisdom-tab" class="tab-content">
|
240 |
+
<div class="grid" id="wisdom-grid">
|
241 |
+
<div class="loading">Loading business wisdom...</div>
|
242 |
+
</div>
|
243 |
+
</div>
|
244 |
+
</div>
|
245 |
+
|
246 |
+
<script>
|
247 |
+
// Tab functionality
|
248 |
+
function showTab(tabName) {
|
249 |
+
// Hide all tabs
|
250 |
+
document.querySelectorAll('.tab-content').forEach(tab => {
|
251 |
+
tab.classList.remove('active');
|
252 |
+
});
|
253 |
+
|
254 |
+
// Remove active class from all buttons
|
255 |
+
document.querySelectorAll('.tab-btn').forEach(btn => {
|
256 |
+
btn.classList.remove('active');
|
257 |
+
});
|
258 |
+
|
259 |
+
// Show selected tab
|
260 |
+
document.getElementById(tabName + '-tab').classList.add('active');
|
261 |
+
|
262 |
+
// Add active class to clicked button
|
263 |
+
event.target.classList.add('active');
|
264 |
+
|
265 |
+
// Load data for the selected tab
|
266 |
+
if (tabName === 'news') {
|
267 |
+
loadNewsData();
|
268 |
+
} else if (tabName === 'wisdom') {
|
269 |
+
loadWisdomData();
|
270 |
+
}
|
271 |
+
}
|
272 |
+
|
273 |
+
// Load news data
|
274 |
+
async function loadNewsData() {
|
275 |
+
try {
|
276 |
+
const response = await fetch('/api/news');
|
277 |
+
const newsData = await response.json();
|
278 |
+
|
279 |
+
if (newsData.error) {
|
280 |
+
document.getElementById('news-grid').innerHTML =
|
281 |
+
`<div class="error">Error loading news: ${newsData.error}</div>`;
|
282 |
+
return;
|
283 |
+
}
|
284 |
+
|
285 |
+
displayNewsData(newsData);
|
286 |
+
|
287 |
+
} catch (error) {
|
288 |
+
document.getElementById('news-grid').innerHTML =
|
289 |
+
'<div class="error">Error loading news data</div>';
|
290 |
+
}
|
291 |
+
}
|
292 |
+
|
293 |
+
// Display news data
|
294 |
+
function displayNewsData(newsData) {
|
295 |
+
const newsGrid = document.getElementById('news-grid');
|
296 |
+
|
297 |
+
if (newsData.length === 0) {
|
298 |
+
newsGrid.innerHTML = '<div class="loading">No news articles found.</div>';
|
299 |
+
return;
|
300 |
+
}
|
301 |
+
|
302 |
+
const imageUrls = [
|
303 |
+
'https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=500',
|
304 |
+
'https://images.unsplash.com/photo-1544716278-ca5e3f4abd8c?w=500',
|
305 |
+
'https://images.unsplash.com/photo-1573496359142-b8d87734a5a2?w=500',
|
306 |
+
'https://images.unsplash.com/photo-1522202176988-66273c2fd55f?w=500',
|
307 |
+
'https://images.unsplash.com/photo-1554224155-6726b3ff858f?w=500'
|
308 |
+
];
|
309 |
+
|
310 |
+
newsGrid.innerHTML = newsData.map((article, index) => `
|
311 |
+
<article class="news-card">
|
312 |
+
<div class="news-card-image" style="background-image: url('${imageUrls[index % imageUrls.length]}');"></div>
|
313 |
+
<div class="news-card-content">
|
314 |
+
<h3 class="news-card-title">${article.title}</h3>
|
315 |
+
<p class="news-card-date">${article.date} β’ ${article.source} β’ ${article.category}</p>
|
316 |
+
<p style="color: var(--muted); font-size: 0.875rem; margin-bottom: 1rem;">${article.description}</p>
|
317 |
+
<a href="#" style="color: var(--brand); text-decoration: none; font-weight: 600; font-size: 0.875rem; text-transform: uppercase;">READ MORE</a>
|
318 |
+
</div>
|
319 |
+
</article>
|
320 |
+
`).join('');
|
321 |
+
}
|
322 |
+
|
323 |
+
// Load business wisdom data
|
324 |
+
async function loadWisdomData() {
|
325 |
+
try {
|
326 |
+
const response = await fetch('/api/business-leaders');
|
327 |
+
const wisdomData = await response.json();
|
328 |
+
|
329 |
+
if (wisdomData.error) {
|
330 |
+
document.getElementById('wisdom-grid').innerHTML =
|
331 |
+
`<div class="error">Error loading wisdom: ${wisdomData.error}</div>`;
|
332 |
+
return;
|
333 |
+
}
|
334 |
+
|
335 |
+
displayWisdomData(wisdomData);
|
336 |
+
|
337 |
+
} catch (error) {
|
338 |
+
document.getElementById('wisdom-grid').innerHTML =
|
339 |
+
'<div class="error">Error loading business wisdom data</div>';
|
340 |
+
}
|
341 |
+
}
|
342 |
+
|
343 |
+
// Display business wisdom data
|
344 |
+
function displayWisdomData(wisdomData) {
|
345 |
+
const wisdomGrid = document.getElementById('wisdom-grid');
|
346 |
+
|
347 |
+
if (wisdomData.length === 0) {
|
348 |
+
wisdomGrid.innerHTML = '<div class="loading">No wisdom quotes found.</div>';
|
349 |
+
return;
|
350 |
+
}
|
351 |
+
|
352 |
+
wisdomGrid.innerHTML = wisdomData.map(quote => `
|
353 |
+
<article class="wisdom-card">
|
354 |
+
<p class="wisdom-quote">${quote.quote}</p>
|
355 |
+
<div class="wisdom-author">β ${quote.author}</div>
|
356 |
+
<div class="wisdom-meta">
|
357 |
+
${quote.category} β’ ${quote.year} β’ ${quote.source}
|
358 |
+
</div>
|
359 |
+
</article>
|
360 |
+
`).join('');
|
361 |
+
}
|
362 |
+
|
363 |
+
// Initialize the page
|
364 |
+
document.addEventListener('DOMContentLoaded', function() {
|
365 |
+
// Load news data by default
|
366 |
+
loadNewsData();
|
367 |
+
});
|
368 |
+
</script>
|
369 |
+
</body>
|
370 |
+
</html>
|
371 |
+
|
372 |
+
|
373 |
+
|
374 |
+
|
375 |
+
|
376 |
+
|
booknap project/community-section.html
ADDED
@@ -0,0 +1,285 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8">
|
5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6 |
+
<title>Booknap - Join Our Community</title>
|
7 |
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap" rel="stylesheet" />
|
8 |
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" />
|
9 |
+
<style>
|
10 |
+
:root {
|
11 |
+
--bg: #0f172a;
|
12 |
+
--card: #0b1223;
|
13 |
+
--muted: #94a3b8;
|
14 |
+
--text: #e2e8f0;
|
15 |
+
--brand: #3b82f6;
|
16 |
+
--brand-2: #6366f1;
|
17 |
+
}
|
18 |
+
|
19 |
+
body {
|
20 |
+
font-family: 'Inter', sans-serif;
|
21 |
+
background: linear-gradient(180deg, #0b1020, #0b1022 30%, #0b1124);
|
22 |
+
color: var(--text);
|
23 |
+
margin: 0;
|
24 |
+
padding: 0;
|
25 |
+
}
|
26 |
+
|
27 |
+
/* Header Styles */
|
28 |
+
.header {
|
29 |
+
position: sticky;
|
30 |
+
top: 0;
|
31 |
+
-webkit-backdrop-filter: blur(8px);
|
32 |
+
backdrop-filter: blur(8px);
|
33 |
+
background: rgba(7,10,20,0.55);
|
34 |
+
z-index: 20;
|
35 |
+
box-shadow: none;
|
36 |
+
}
|
37 |
+
|
38 |
+
.nav {
|
39 |
+
border-bottom: 1px solid rgba(255,255,255,0.06);
|
40 |
+
}
|
41 |
+
|
42 |
+
.nav-container {
|
43 |
+
display: flex;
|
44 |
+
align-items: center;
|
45 |
+
gap: 2rem;
|
46 |
+
max-width: 1200px;
|
47 |
+
margin: 0 auto;
|
48 |
+
padding: 0 20px;
|
49 |
+
}
|
50 |
+
|
51 |
+
.nav-logo {
|
52 |
+
display: flex;
|
53 |
+
align-items: center;
|
54 |
+
gap: 0.5rem;
|
55 |
+
color: white;
|
56 |
+
font-size: 1.5rem;
|
57 |
+
font-weight: 700;
|
58 |
+
text-decoration: none;
|
59 |
+
}
|
60 |
+
|
61 |
+
.nav-logo i {
|
62 |
+
font-size: 1.8rem;
|
63 |
+
color: var(--brand);
|
64 |
+
}
|
65 |
+
|
66 |
+
.nav-menu {
|
67 |
+
display: flex;
|
68 |
+
list-style: none;
|
69 |
+
gap: 2rem;
|
70 |
+
margin-left: auto;
|
71 |
+
}
|
72 |
+
|
73 |
+
.nav-link {
|
74 |
+
color: var(--muted);
|
75 |
+
text-decoration: none;
|
76 |
+
font-weight: 600;
|
77 |
+
transition: color 0.3s ease;
|
78 |
+
}
|
79 |
+
|
80 |
+
.nav-link:hover, .nav-link.active {
|
81 |
+
color: var(--text);
|
82 |
+
}
|
83 |
+
|
84 |
+
.nav-login {
|
85 |
+
margin-left: 0;
|
86 |
+
}
|
87 |
+
|
88 |
+
.login-btn {
|
89 |
+
background: linear-gradient(90deg, #3b82f6, #6366f1);
|
90 |
+
color: white;
|
91 |
+
padding: 0.75rem 1.5rem;
|
92 |
+
border-radius: 8px;
|
93 |
+
text-decoration: none;
|
94 |
+
font-weight: 600;
|
95 |
+
transition: background-color 0.2s ease;
|
96 |
+
display: inline-block;
|
97 |
+
}
|
98 |
+
|
99 |
+
.login-btn:hover {
|
100 |
+
background: linear-gradient(90deg, #2563eb, #4f46e5);
|
101 |
+
}
|
102 |
+
|
103 |
+
/* Community Section Styles */
|
104 |
+
.community-section {
|
105 |
+
background: transparent;
|
106 |
+
padding: 4rem 0;
|
107 |
+
margin-top: 0;
|
108 |
+
}
|
109 |
+
|
110 |
+
.community-container {
|
111 |
+
max-width: 1200px;
|
112 |
+
margin: 0 auto;
|
113 |
+
padding: 0 20px;
|
114 |
+
display: grid;
|
115 |
+
grid-template-columns: 1fr 1fr;
|
116 |
+
gap: 4rem;
|
117 |
+
align-items: center;
|
118 |
+
}
|
119 |
+
|
120 |
+
.community-content {
|
121 |
+
color: var(--text);
|
122 |
+
}
|
123 |
+
|
124 |
+
.community-title {
|
125 |
+
font-size: 3.5rem;
|
126 |
+
font-weight: 800;
|
127 |
+
line-height: 1.1;
|
128 |
+
margin-bottom: 1.5rem;
|
129 |
+
color: var(--text);
|
130 |
+
}
|
131 |
+
|
132 |
+
.community-description {
|
133 |
+
font-size: 1.125rem;
|
134 |
+
line-height: 1.7;
|
135 |
+
color: var(--muted);
|
136 |
+
margin-bottom: 2.5rem;
|
137 |
+
}
|
138 |
+
|
139 |
+
.community-buttons {
|
140 |
+
display: flex;
|
141 |
+
gap: 1rem;
|
142 |
+
flex-wrap: wrap;
|
143 |
+
}
|
144 |
+
|
145 |
+
.btn {
|
146 |
+
display: inline-flex;
|
147 |
+
align-items: center;
|
148 |
+
gap: 0.75rem;
|
149 |
+
padding: 0.875rem 1.5rem;
|
150 |
+
border: 1px solid #d1d5db;
|
151 |
+
border-radius: 8px;
|
152 |
+
background: white;
|
153 |
+
color: #374151;
|
154 |
+
text-decoration: none;
|
155 |
+
font-weight: 500;
|
156 |
+
font-size: 0.875rem;
|
157 |
+
transition: all 0.2s ease;
|
158 |
+
}
|
159 |
+
|
160 |
+
.btn:hover {
|
161 |
+
border-color: #9ca3af;
|
162 |
+
background: #f9fafb;
|
163 |
+
}
|
164 |
+
|
165 |
+
.btn-google {
|
166 |
+
border-color: #d1d5db;
|
167 |
+
}
|
168 |
+
|
169 |
+
.btn-email {
|
170 |
+
border-color: #d1d5db;
|
171 |
+
}
|
172 |
+
|
173 |
+
.google-icon {
|
174 |
+
width: 18px;
|
175 |
+
height: 18px;
|
176 |
+
background: conic-gradient(from -45deg, #ea4335 110deg, #4285f4 90deg 180deg, #34a853 180deg 270deg, #fbbc05 270deg);
|
177 |
+
border-radius: 2px;
|
178 |
+
position: relative;
|
179 |
+
}
|
180 |
+
|
181 |
+
.google-icon::before {
|
182 |
+
content: '';
|
183 |
+
position: absolute;
|
184 |
+
top: 50%;
|
185 |
+
left: 50%;
|
186 |
+
transform: translate(-50%, -50%);
|
187 |
+
width: 8px;
|
188 |
+
height: 8px;
|
189 |
+
background: white;
|
190 |
+
border-radius: 1px;
|
191 |
+
}
|
192 |
+
|
193 |
+
/* Right-side image */
|
194 |
+
.community-image-wrap {
|
195 |
+
display: flex;
|
196 |
+
align-items: center;
|
197 |
+
justify-content: center;
|
198 |
+
min-height: 220px;
|
199 |
+
}
|
200 |
+
.community-image {
|
201 |
+
width: 100%;
|
202 |
+
max-width: 380px;
|
203 |
+
height: auto;
|
204 |
+
border-radius: 12px;
|
205 |
+
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.08);
|
206 |
+
object-fit: contain;
|
207 |
+
display: block;
|
208 |
+
}
|
209 |
+
|
210 |
+
/* Illustration styles removed: using a single image on the right side */
|
211 |
+
|
212 |
+
/* Responsive Design */
|
213 |
+
@media (max-width: 768px) {
|
214 |
+
.community-container {
|
215 |
+
grid-template-columns: 1fr;
|
216 |
+
gap: 2rem;
|
217 |
+
}
|
218 |
+
|
219 |
+
.community-title {
|
220 |
+
font-size: 2.5rem;
|
221 |
+
}
|
222 |
+
|
223 |
+
.community-buttons {
|
224 |
+
flex-direction: column;
|
225 |
+
}
|
226 |
+
|
227 |
+
/* no right-side illustration adjustments needed */
|
228 |
+
}
|
229 |
+
</style>
|
230 |
+
</head>
|
231 |
+
<body>
|
232 |
+
<!-- Header -->
|
233 |
+
<header class="header">
|
234 |
+
<nav class="nav">
|
235 |
+
<div class="nav-container">
|
236 |
+
<div class="nav-logo">
|
237 |
+
<i class="fas fa-book-open"></i>
|
238 |
+
<span>booknap</span>
|
239 |
+
</div>
|
240 |
+
<ul class="nav-menu">
|
241 |
+
<li><a href="#" class="nav-link active">Home</a></li>
|
242 |
+
<li><a href="#" class="nav-link">Book Summaries</a></li>
|
243 |
+
<li><a href="#" class="nav-link">Pricing</a></li>
|
244 |
+
<li><a href="#" class="nav-link">Blog</a></li>
|
245 |
+
</ul>
|
246 |
+
<div class="nav-login">
|
247 |
+
<a href="login.html" class="login-btn">Login</a>
|
248 |
+
</div>
|
249 |
+
</div>
|
250 |
+
</nav>
|
251 |
+
</header>
|
252 |
+
|
253 |
+
<!-- Community Section -->
|
254 |
+
<section class="community-section">
|
255 |
+
<div class="community-container">
|
256 |
+
<!-- Left Side - Content -->
|
257 |
+
<div class="community-content">
|
258 |
+
<h1 class="community-title">
|
259 |
+
Level up with the largest<br>
|
260 |
+
<span style="color: var(--brand);">reading community</span>
|
261 |
+
</h1>
|
262 |
+
|
263 |
+
<p class="community-description">
|
264 |
+
Join over 25M+ book lovers to share insights, discuss ideas, and stay up-to-date on all the latest books and reading techniques. Discover a huge repository of community-published book summaries, reviews & reading guides for your next learning journey.
|
265 |
+
</p>
|
266 |
+
|
267 |
+
</div>
|
268 |
+
|
269 |
+
<!-- Right Side - Image -->
|
270 |
+
<div class="community-image-wrap">
|
271 |
+
<img class="community-image" src="https://i.pinimg.com/736x/f4/a0/48/f4a0480397a1c019a2a1a238b2ffc594.jpg" alt="Reading illustration" />
|
272 |
+
</div>
|
273 |
+
|
274 |
+
</div>
|
275 |
+
</section>
|
276 |
+
|
277 |
+
<!-- Rest of your content can go here -->
|
278 |
+
<div style="background: var(--bg); padding: 2rem; color: var(--text);">
|
279 |
+
<div style="max-width: 1200px; margin: 0 auto;">
|
280 |
+
<h2>Continue Your Reading Journey</h2>
|
281 |
+
<p>Explore our book summaries, join reading discussions, and discover new insights with our community of book lovers.</p>
|
282 |
+
</div>
|
283 |
+
</div>
|
284 |
+
</body>
|
285 |
+
</html>
|
booknap project/data/news.json
ADDED
@@ -0,0 +1,86 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"articles": [
|
3 |
+
{
|
4 |
+
"id": 1,
|
5 |
+
"title": "The Future of Artificial Intelligence in 2024",
|
6 |
+
"description": "Exploring the latest developments in AI technology and their impact on various industries.",
|
7 |
+
"date": "2024-01-15",
|
8 |
+
"source": "Tech News",
|
9 |
+
"category": "Technology",
|
10 |
+
"image": "https://images.unsplash.com/photo-1485827404703-89b55fcc595e?w=500",
|
11 |
+
"tags": ["AI", "Technology", "Innovation"]
|
12 |
+
},
|
13 |
+
{
|
14 |
+
"id": 2,
|
15 |
+
"title": "Sustainable Business Practices That Drive Growth",
|
16 |
+
"description": "How companies are implementing eco-friendly strategies while maintaining profitability.",
|
17 |
+
"date": "2024-01-14",
|
18 |
+
"source": "Business Weekly",
|
19 |
+
"category": "Business",
|
20 |
+
"image": "https://images.unsplash.com/photo-1554224155-6726b3ff858f?w=500",
|
21 |
+
"tags": ["Sustainability", "Business", "Growth"]
|
22 |
+
},
|
23 |
+
{
|
24 |
+
"id": 3,
|
25 |
+
"title": "Mental Health Awareness in the Digital Age",
|
26 |
+
"description": "Understanding the impact of social media and technology on mental well-being.",
|
27 |
+
"date": "2024-01-13",
|
28 |
+
"source": "Health Journal",
|
29 |
+
"category": "Health",
|
30 |
+
"image": "https://images.unsplash.com/photo-1573496359142-b8d87734a5a2?w=500",
|
31 |
+
"tags": ["Mental Health", "Digital", "Wellness"]
|
32 |
+
},
|
33 |
+
{
|
34 |
+
"id": 4,
|
35 |
+
"title": "Climate Change Solutions: What Works",
|
36 |
+
"description": "Evidence-based approaches to addressing climate change at individual and corporate levels.",
|
37 |
+
"date": "2024-01-12",
|
38 |
+
"source": "Environmental Times",
|
39 |
+
"category": "Environment",
|
40 |
+
"image": "https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=500",
|
41 |
+
"tags": ["Climate", "Environment", "Solutions"]
|
42 |
+
},
|
43 |
+
{
|
44 |
+
"id": 5,
|
45 |
+
"title": "The Rise of Remote Work Culture",
|
46 |
+
"description": "How remote work is reshaping company culture and employee expectations.",
|
47 |
+
"date": "2024-01-11",
|
48 |
+
"source": "Workplace Insights",
|
49 |
+
"category": "Work",
|
50 |
+
"image": "https://images.unsplash.com/photo-1522202176988-66273c2fd55f?w=500",
|
51 |
+
"tags": ["Remote Work", "Culture", "Workplace"]
|
52 |
+
},
|
53 |
+
{
|
54 |
+
"id": 6,
|
55 |
+
"title": "Digital Privacy in the Age of Big Data",
|
56 |
+
"description": "Protecting personal information in an increasingly connected world.",
|
57 |
+
"date": "2024-01-10",
|
58 |
+
"source": "Privacy Today",
|
59 |
+
"category": "Technology",
|
60 |
+
"image": "https://images.unsplash.com/photo-1544716278-ca5e3f4abd8c?w=500",
|
61 |
+
"tags": ["Privacy", "Data", "Security"]
|
62 |
+
}
|
63 |
+
],
|
64 |
+
"categories": [
|
65 |
+
"Technology",
|
66 |
+
"Business",
|
67 |
+
"Health",
|
68 |
+
"Environment",
|
69 |
+
"Work"
|
70 |
+
],
|
71 |
+
"sources": [
|
72 |
+
"Tech News",
|
73 |
+
"Business Weekly",
|
74 |
+
"Health Journal",
|
75 |
+
"Environmental Times",
|
76 |
+
"Workplace Insights",
|
77 |
+
"Privacy Today"
|
78 |
+
]
|
79 |
+
}
|
80 |
+
|
81 |
+
|
82 |
+
|
83 |
+
|
84 |
+
|
85 |
+
|
86 |
+
|
booknap project/database_schema.sql
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
-- Database schema for Booknap user authentication
|
2 |
+
-- Run this in your PostgreSQL database
|
3 |
+
|
4 |
+
-- Create users table
|
5 |
+
CREATE TABLE IF NOT EXISTS users (
|
6 |
+
id SERIAL PRIMARY KEY,
|
7 |
+
full_name VARCHAR(255) NOT NULL,
|
8 |
+
email VARCHAR(255) UNIQUE NOT NULL,
|
9 |
+
password VARCHAR(255) NOT NULL,
|
10 |
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
11 |
+
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
12 |
+
);
|
13 |
+
|
14 |
+
-- Create index on email for faster lookups
|
15 |
+
CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);
|
16 |
+
|
17 |
+
-- Insert a sample user for testing (password: test123)
|
18 |
+
-- INSERT INTO users (full_name, email, password) VALUES ('Test User', 'test@example.com', 'test123');
|
19 |
+
|
20 |
+
-- Note: In production, passwords should be hashed using bcrypt or similar
|
21 |
+
-- The current implementation stores plaintext passwords for demo purposes only
|
booknap project/json-blog.html
ADDED
@@ -0,0 +1,272 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8">
|
5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6 |
+
<title>Blog with JSON Dataset</title>
|
7 |
+
<style>
|
8 |
+
body {
|
9 |
+
font-family: 'Inter', sans-serif;
|
10 |
+
background: linear-gradient(180deg, #0b1020, #0b1022 30%, #0b1124);
|
11 |
+
color: #e2e8f0;
|
12 |
+
margin: 0;
|
13 |
+
padding: 20px;
|
14 |
+
}
|
15 |
+
|
16 |
+
.container {
|
17 |
+
max-width: 1200px;
|
18 |
+
margin: 0 auto;
|
19 |
+
}
|
20 |
+
|
21 |
+
.controls {
|
22 |
+
display: flex;
|
23 |
+
gap: 1rem;
|
24 |
+
margin: 2rem 0;
|
25 |
+
flex-wrap: wrap;
|
26 |
+
}
|
27 |
+
|
28 |
+
.search-bar, .category-filter {
|
29 |
+
background: rgba(255, 255, 255, 0.1);
|
30 |
+
border: 1px solid rgba(255, 255, 255, 0.2);
|
31 |
+
border-radius: 25px;
|
32 |
+
padding: 0.75rem 1.5rem;
|
33 |
+
color: #e2e8f0;
|
34 |
+
}
|
35 |
+
|
36 |
+
.search-bar {
|
37 |
+
flex: 1;
|
38 |
+
min-width: 200px;
|
39 |
+
}
|
40 |
+
|
41 |
+
.category-filter {
|
42 |
+
min-width: 150px;
|
43 |
+
}
|
44 |
+
|
45 |
+
.blog-grid {
|
46 |
+
display: grid;
|
47 |
+
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
|
48 |
+
gap: 2rem;
|
49 |
+
margin-top: 2rem;
|
50 |
+
}
|
51 |
+
|
52 |
+
.blog-card {
|
53 |
+
background: rgba(255, 255, 255, 0.05);
|
54 |
+
border-radius: 16px;
|
55 |
+
overflow: hidden;
|
56 |
+
border: 1px solid rgba(255, 255, 255, 0.1);
|
57 |
+
transition: transform 0.3s ease;
|
58 |
+
}
|
59 |
+
|
60 |
+
.blog-card:hover {
|
61 |
+
transform: translateY(-8px);
|
62 |
+
}
|
63 |
+
|
64 |
+
.blog-card-image {
|
65 |
+
width: 100%;
|
66 |
+
height: 200px;
|
67 |
+
background-size: cover;
|
68 |
+
background-position: center;
|
69 |
+
}
|
70 |
+
|
71 |
+
.blog-card-content {
|
72 |
+
padding: 1.5rem;
|
73 |
+
}
|
74 |
+
|
75 |
+
.blog-card-title {
|
76 |
+
font-size: 1.25rem;
|
77 |
+
font-weight: 600;
|
78 |
+
margin-bottom: 0.5rem;
|
79 |
+
}
|
80 |
+
|
81 |
+
.blog-card-date {
|
82 |
+
color: #94a3b8;
|
83 |
+
font-size: 0.875rem;
|
84 |
+
margin-bottom: 1rem;
|
85 |
+
}
|
86 |
+
|
87 |
+
.blog-card-link {
|
88 |
+
color: #8b5cf6;
|
89 |
+
text-decoration: none;
|
90 |
+
font-weight: 600;
|
91 |
+
font-size: 0.875rem;
|
92 |
+
text-transform: uppercase;
|
93 |
+
}
|
94 |
+
|
95 |
+
.tags {
|
96 |
+
display: flex;
|
97 |
+
gap: 0.5rem;
|
98 |
+
margin-top: 1rem;
|
99 |
+
flex-wrap: wrap;
|
100 |
+
}
|
101 |
+
|
102 |
+
.tag {
|
103 |
+
background: rgba(139, 92, 246, 0.2);
|
104 |
+
color: #a78bfa;
|
105 |
+
padding: 0.25rem 0.75rem;
|
106 |
+
border-radius: 15px;
|
107 |
+
font-size: 0.75rem;
|
108 |
+
}
|
109 |
+
|
110 |
+
.loading {
|
111 |
+
text-align: center;
|
112 |
+
padding: 2rem;
|
113 |
+
color: #94a3b8;
|
114 |
+
}
|
115 |
+
|
116 |
+
.stats {
|
117 |
+
display: flex;
|
118 |
+
gap: 2rem;
|
119 |
+
margin: 1rem 0;
|
120 |
+
color: #94a3b8;
|
121 |
+
font-size: 0.875rem;
|
122 |
+
}
|
123 |
+
</style>
|
124 |
+
</head>
|
125 |
+
<body>
|
126 |
+
<div class="container">
|
127 |
+
<h1>Blog with JSON Dataset</h1>
|
128 |
+
|
129 |
+
<div class="stats" id="stats">
|
130 |
+
<span>Loading...</span>
|
131 |
+
</div>
|
132 |
+
|
133 |
+
<div class="controls">
|
134 |
+
<input type="text" class="search-bar" placeholder="Search articles..." id="searchInput">
|
135 |
+
<select class="category-filter" id="categoryFilter" aria-label="Filter by category">
|
136 |
+
<option value="">All Categories</option>
|
137 |
+
</select>
|
138 |
+
</div>
|
139 |
+
|
140 |
+
<div class="blog-grid" id="blogGrid">
|
141 |
+
<div class="loading">Loading articles...</div>
|
142 |
+
</div>
|
143 |
+
</div>
|
144 |
+
|
145 |
+
<script>
|
146 |
+
let allArticles = [];
|
147 |
+
let filteredArticles = [];
|
148 |
+
|
149 |
+
// Load data from JSON file
|
150 |
+
async function loadDataset() {
|
151 |
+
try {
|
152 |
+
const response = await fetch('data/news.json');
|
153 |
+
const data = await response.json();
|
154 |
+
allArticles = data.articles;
|
155 |
+
filteredArticles = [...allArticles];
|
156 |
+
|
157 |
+
// Populate category filter
|
158 |
+
populateCategoryFilter(data.categories);
|
159 |
+
|
160 |
+
// Display articles
|
161 |
+
displayArticles(filteredArticles);
|
162 |
+
|
163 |
+
// Update stats
|
164 |
+
updateStats();
|
165 |
+
|
166 |
+
} catch (error) {
|
167 |
+
console.error('Error loading dataset:', error);
|
168 |
+
document.getElementById('blogGrid').innerHTML =
|
169 |
+
'<div class="loading">Error loading data. Please check if data/news.json exists.</div>';
|
170 |
+
}
|
171 |
+
}
|
172 |
+
|
173 |
+
// Populate category filter dropdown
|
174 |
+
function populateCategoryFilter(categories) {
|
175 |
+
const categoryFilter = document.getElementById('categoryFilter');
|
176 |
+
categories.forEach(category => {
|
177 |
+
const option = document.createElement('option');
|
178 |
+
option.value = category;
|
179 |
+
option.textContent = category;
|
180 |
+
categoryFilter.appendChild(option);
|
181 |
+
});
|
182 |
+
}
|
183 |
+
|
184 |
+
// Create article card
|
185 |
+
function createArticleCard(article) {
|
186 |
+
const tags = article.tags ? article.tags.map(tag =>
|
187 |
+
`<span class="tag">${tag}</span>`
|
188 |
+
).join('') : '';
|
189 |
+
|
190 |
+
return `
|
191 |
+
<article class="blog-card">
|
192 |
+
<div class="blog-card-image" style="background-image: url('${article.image}');"></div>
|
193 |
+
<div class="blog-card-content">
|
194 |
+
<h3 class="blog-card-title">${article.title}</h3>
|
195 |
+
<p class="blog-card-date">${article.date} β’ ${article.source} β’ ${article.category}</p>
|
196 |
+
<p style="color: #94a3b8; font-size: 0.875rem; margin-bottom: 1rem;">${article.description}</p>
|
197 |
+
<div class="tags">${tags}</div>
|
198 |
+
<a href="#" class="blog-card-link">READ MORE</a>
|
199 |
+
</div>
|
200 |
+
</article>
|
201 |
+
`;
|
202 |
+
}
|
203 |
+
|
204 |
+
// Display articles
|
205 |
+
function displayArticles(articles) {
|
206 |
+
const blogGrid = document.getElementById('blogGrid');
|
207 |
+
if (articles.length === 0) {
|
208 |
+
blogGrid.innerHTML = '<div class="loading">No articles found.</div>';
|
209 |
+
} else {
|
210 |
+
blogGrid.innerHTML = articles.map(createArticleCard).join('');
|
211 |
+
}
|
212 |
+
}
|
213 |
+
|
214 |
+
// Filter articles
|
215 |
+
function filterArticles() {
|
216 |
+
const searchTerm = document.getElementById('searchInput').value.toLowerCase();
|
217 |
+
const selectedCategory = document.getElementById('categoryFilter').value;
|
218 |
+
|
219 |
+
filteredArticles = allArticles.filter(article => {
|
220 |
+
const matchesSearch =
|
221 |
+
article.title.toLowerCase().includes(searchTerm) ||
|
222 |
+
article.description.toLowerCase().includes(searchTerm) ||
|
223 |
+
article.tags.some(tag => tag.toLowerCase().includes(searchTerm));
|
224 |
+
|
225 |
+
const matchesCategory = !selectedCategory || article.category === selectedCategory;
|
226 |
+
|
227 |
+
return matchesSearch && matchesCategory;
|
228 |
+
});
|
229 |
+
|
230 |
+
displayArticles(filteredArticles);
|
231 |
+
updateStats();
|
232 |
+
}
|
233 |
+
|
234 |
+
// Update statistics
|
235 |
+
function updateStats() {
|
236 |
+
const stats = document.getElementById('stats');
|
237 |
+
stats.innerHTML = `
|
238 |
+
<span>Total Articles: ${allArticles.length}</span>
|
239 |
+
<span>Showing: ${filteredArticles.length}</span>
|
240 |
+
<span>Categories: ${new Set(allArticles.map(a => a.category)).size}</span>
|
241 |
+
`;
|
242 |
+
}
|
243 |
+
|
244 |
+
// Initialize the page
|
245 |
+
document.addEventListener('DOMContentLoaded', function() {
|
246 |
+
// Load dataset
|
247 |
+
loadDataset();
|
248 |
+
|
249 |
+
// Add event listeners
|
250 |
+
document.getElementById('searchInput').addEventListener('input', filterArticles);
|
251 |
+
document.getElementById('categoryFilter').addEventListener('change', filterArticles);
|
252 |
+
});
|
253 |
+
|
254 |
+
// Example functions for data manipulation
|
255 |
+
function getArticlesByCategory(category) {
|
256 |
+
return allArticles.filter(article => article.category === category);
|
257 |
+
}
|
258 |
+
|
259 |
+
function getLatestArticles(count = 3) {
|
260 |
+
return allArticles
|
261 |
+
.sort((a, b) => new Date(b.date) - new Date(a.date))
|
262 |
+
.slice(0, count);
|
263 |
+
}
|
264 |
+
|
265 |
+
function searchByTags(tags) {
|
266 |
+
return allArticles.filter(article =>
|
267 |
+
tags.some(tag => article.tags.includes(tag))
|
268 |
+
);
|
269 |
+
}
|
270 |
+
</script>
|
271 |
+
</body>
|
272 |
+
</html>
|
booknap project/login.html
ADDED
@@ -0,0 +1,120 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8" />
|
5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
6 |
+
<title>Login - booknap</title>
|
7 |
+
<link rel="stylesheet" href="styles.css" />
|
8 |
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap" rel="stylesheet" />
|
9 |
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" />
|
10 |
+
<style>
|
11 |
+
:root {
|
12 |
+
--bg: #0f172a;
|
13 |
+
--card: #0b1223;
|
14 |
+
--muted: #94a3b8;
|
15 |
+
--text: #e2e8f0;
|
16 |
+
--brand: #3b82f6;
|
17 |
+
--brand-2: #6366f1;
|
18 |
+
}
|
19 |
+
body { background: linear-gradient(180deg, #0b1020, #0b1022 30%, #0b1124); min-height: 100vh; color: var(--text); font-family: 'Inter', system-ui, -apple-system, Segoe UI, Roboto, sans-serif; margin: 0; }
|
20 |
+
.header { position: sticky; top: 0; -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px); background: rgba(7,10,20,0.55); z-index: 20; box-shadow: none; }
|
21 |
+
.nav { border-bottom: 1px solid rgba(255,255,255,0.06); }
|
22 |
+
.nav-container { max-width: 1200px; margin: 0 auto; padding: 0 20px; display: flex; align-items: center; gap: 2rem; }
|
23 |
+
.nav-logo i { color: var(--brand); }
|
24 |
+
.nav-link { color: var(--muted); text-decoration: none; font-weight: 600; }
|
25 |
+
.nav-link:hover, .nav-link.active { color: var(--text); }
|
26 |
+
.login-btn { background: linear-gradient(90deg, #3b82f6, #6366f1); color: white; padding: 0.75rem 1.5rem; border-radius: 8px; text-decoration: none; font-weight: 600; display: inline-block; }
|
27 |
+
.login-btn:hover { background: linear-gradient(90deg, #2563eb, #4f46e5); }
|
28 |
+
|
29 |
+
.auth { display: grid; place-items: center; padding: 4rem 1rem; }
|
30 |
+
.auth-card { width: 100%; max-width: 480px; background: rgba(255,255,255,0.04); border: 1px solid rgba(255,255,255,0.08); border-radius: 16px; padding: 2rem; box-shadow: 0 16px 40px rgba(0,0,0,0.12); -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px); }
|
31 |
+
.auth-title { font-size: 1.75rem; font-weight: 800; margin: 0 0 0.25rem 0; }
|
32 |
+
.auth-sub { color: var(--muted); margin: 0 0 1.5rem 0; }
|
33 |
+
.field { display: grid; gap: 0.4rem; margin-bottom: 1rem; }
|
34 |
+
.label { font-weight: 600; font-size: 0.9rem; color: #cbd5e1; }
|
35 |
+
.input { background: rgba(15,23,42,0.7); color: var(--text); border: 1px solid rgba(255,255,255,0.12); border-radius: 10px; padding: 0.75rem 0.9rem; outline: none; transition: border-color 0.2s ease, box-shadow 0.2s ease; }
|
36 |
+
.input:focus { border-color: rgba(59,130,246,0.55); box-shadow: 0 0 0 3px rgba(59,130,246,0.15); }
|
37 |
+
.row { display: flex; justify-content: space-between; align-items: center; gap: 0.75rem; margin: 0.25rem 0 1rem; }
|
38 |
+
.muted-link { color: var(--muted); font-size: 0.9rem; text-decoration: none; }
|
39 |
+
.muted-link:hover { color: #cbd5e1; }
|
40 |
+
.submit { width: 100%; display: inline-block; background: linear-gradient(90deg, var(--brand), var(--brand-2)); color: white; font-weight: 800; text-align: center; padding: 0.85rem 1rem; border-radius: 12px; text-decoration: none; border: 0; cursor: pointer; }
|
41 |
+
.or { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 0.75rem; margin: 1.25rem 0; color: var(--muted); }
|
42 |
+
.or::before, .or::after { content: ""; height: 1px; background: rgba(255,255,255,0.15); }
|
43 |
+
.oauth { width: 100%; display: inline-flex; align-items: center; justify-content: center; gap: 0.6rem; background: rgba(255,255,255,0.06); color: var(--text); padding: 0.75rem 1rem; border-radius: 10px; text-decoration: none; font-weight: 700; border: 1px solid rgba(255,255,255,0.12); }
|
44 |
+
.footer-note { margin-top: 1rem; color: var(--muted); font-size: 0.95rem; text-align: center; }
|
45 |
+
.footer-note a { color: #93c5fd; text-decoration: none; font-weight: 600; }
|
46 |
+
</style>
|
47 |
+
</head>
|
48 |
+
<body>
|
49 |
+
<header class="header">
|
50 |
+
<nav class="nav">
|
51 |
+
<div class="nav-container">
|
52 |
+
<div class="nav-logo">
|
53 |
+
<i class="fas fa-book-open"></i>
|
54 |
+
<span>booknap</span>
|
55 |
+
</div>
|
56 |
+
<ul class="nav-menu" style="display:flex; gap:2rem; list-style:none; margin-left:auto;">
|
57 |
+
<li><a href="books.html" class="nav-link">Home</a></li>
|
58 |
+
<li><a href="pricing.html" class="nav-link">Pricing</a></li>
|
59 |
+
<li><a href="blog.html" class="nav-link">Blog</a></li>
|
60 |
+
</ul>
|
61 |
+
<div class="nav-login">
|
62 |
+
<a href="login.html" class="login-btn">Login</a>
|
63 |
+
</div>
|
64 |
+
</div>
|
65 |
+
</nav>
|
66 |
+
</header>
|
67 |
+
|
68 |
+
<main class="auth">
|
69 |
+
<section class="auth-card">
|
70 |
+
<h1 class="auth-title">Welcome back</h1>
|
71 |
+
<p class="auth-sub">Sign in to continue your reading journey</p>
|
72 |
+
<form id="loginForm">
|
73 |
+
<div class="field">
|
74 |
+
<label class="label" for="email">Email</label>
|
75 |
+
<input class="input" id="email" name="email" type="email" placeholder="you@example.com" required />
|
76 |
+
</div>
|
77 |
+
<div class="field">
|
78 |
+
<label class="label" for="password">Password</label>
|
79 |
+
<input class="input" id="password" name="password" type="password" placeholder="β’β’β’β’β’β’β’β’" required />
|
80 |
+
</div>
|
81 |
+
<div class="row">
|
82 |
+
<label style="display:flex; align-items:center; gap:0.5rem; color:#cbd5e1;">
|
83 |
+
<input type="checkbox" style="accent-color:#3b82f6;" /> Remember me
|
84 |
+
</label>
|
85 |
+
<a class="muted-link" href="#">Forgot password?</a>
|
86 |
+
</div>
|
87 |
+
<button class="submit" type="submit">Sign in</button>
|
88 |
+
</form>
|
89 |
+
<div class="or">or</div>
|
90 |
+
<a class="oauth" href="#"><i class="fab fa-google"></i> Continue with Google</a>
|
91 |
+
<p class="footer-note">New to booknap? <a href="signup.html">Create an account</a></p>
|
92 |
+
</section>
|
93 |
+
</main>
|
94 |
+
<script>
|
95 |
+
document.getElementById('loginForm').addEventListener('submit', async function(e) {
|
96 |
+
e.preventDefault();
|
97 |
+
const email = document.getElementById('email').value.trim();
|
98 |
+
const password = document.getElementById('password').value;
|
99 |
+
try {
|
100 |
+
const res = await fetch('/login', {
|
101 |
+
method: 'POST',
|
102 |
+
headers: { 'Content-Type': 'application/json' },
|
103 |
+
body: JSON.stringify({ email, password })
|
104 |
+
});
|
105 |
+
const data = await res.json();
|
106 |
+
if (!res.ok) {
|
107 |
+
alert(data.error || 'Login failed');
|
108 |
+
return;
|
109 |
+
}
|
110 |
+
alert('Logged in as ' + data.user.email);
|
111 |
+
window.location.href = 'books.html';
|
112 |
+
} catch (err) {
|
113 |
+
alert('Network error: ' + err.message);
|
114 |
+
}
|
115 |
+
});
|
116 |
+
</script>
|
117 |
+
</body>
|
118 |
+
</html>
|
119 |
+
|
120 |
+
|
booknap project/pricing.html
ADDED
@@ -0,0 +1,521 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8" />
|
5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
6 |
+
<title>Pricing - booknap</title>
|
7 |
+
<link rel="stylesheet" href="styles.css" />
|
8 |
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap" rel="stylesheet" />
|
9 |
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" />
|
10 |
+
<style>
|
11 |
+
:root {
|
12 |
+
--bg: #0f172a;
|
13 |
+
--card: #0b1223;
|
14 |
+
--muted: #94a3b8;
|
15 |
+
--text: #e2e8f0;
|
16 |
+
--brand: #3b82f6;
|
17 |
+
--brand-2: #6366f1;
|
18 |
+
}
|
19 |
+
body { background: linear-gradient(180deg, #0b1020, #0b1022 30%, #0b1124); color: var(--text); font-family: 'Inter', system-ui, -apple-system, Segoe UI, Roboto, sans-serif; }
|
20 |
+
.container { max-width: 100%; margin: 0 auto; padding: 0 20px; }
|
21 |
+
/* Match pricing header/nav styling */
|
22 |
+
.header { position: sticky; top: 0; -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px); background: rgba(7,10,20,0.55); z-index: 20; box-shadow: none; }
|
23 |
+
.nav { border-bottom: 1px solid rgba(255,255,255,0.06); }
|
24 |
+
.nav-logo i { color: var(--brand); }
|
25 |
+
.nav-link { color: var(--muted); text-decoration: none; font-weight: 600; }
|
26 |
+
.nav-link:hover, .nav-link.active { color: var(--text); }
|
27 |
+
.login-btn { background: var(--brand); color: white; padding: 0.6rem 1.1rem; border-radius: 9px; text-decoration: none; font-weight: 700; display: inline-block; }
|
28 |
+
|
29 |
+
/* Navigation Login Button */
|
30 |
+
.nav-container {
|
31 |
+
display: flex;
|
32 |
+
align-items: center;
|
33 |
+
gap: 2rem;
|
34 |
+
}
|
35 |
+
|
36 |
+
.nav-menu {
|
37 |
+
display: flex;
|
38 |
+
align-items: center;
|
39 |
+
gap: 2rem;
|
40 |
+
margin-left: auto;
|
41 |
+
}
|
42 |
+
|
43 |
+
.nav-login {
|
44 |
+
margin-left: 0;
|
45 |
+
}
|
46 |
+
|
47 |
+
.login-btn {
|
48 |
+
background: linear-gradient(90deg, #3b82f6, #6366f1);
|
49 |
+
color: white;
|
50 |
+
padding: 0.75rem 1.5rem;
|
51 |
+
border-radius: 8px;
|
52 |
+
text-decoration: none;
|
53 |
+
font-weight: 600;
|
54 |
+
transition: background-color 0.2s ease;
|
55 |
+
display: inline-block;
|
56 |
+
}
|
57 |
+
|
58 |
+
.login-btn:hover {
|
59 |
+
background: linear-gradient(90deg, #2563eb, #4f46e5);
|
60 |
+
}
|
61 |
+
|
62 |
+
.signup-btn {
|
63 |
+
background: transparent;
|
64 |
+
color: var(--text);
|
65 |
+
padding: 0.6rem 1.1rem;
|
66 |
+
border: 2px solid rgba(255, 255, 255, 0.2);
|
67 |
+
border-radius: 9px;
|
68 |
+
text-decoration: none;
|
69 |
+
font-weight: 700;
|
70 |
+
display: inline-block;
|
71 |
+
margin-left: 0.5rem;
|
72 |
+
transition: all 0.2s ease;
|
73 |
+
}
|
74 |
+
|
75 |
+
.signup-btn:hover {
|
76 |
+
background: rgba(255, 255, 255, 0.1);
|
77 |
+
border-color: rgba(255, 255, 255, 0.4);
|
78 |
+
}
|
79 |
+
|
80 |
+
/* Search Bar Styles */
|
81 |
+
.search-container {
|
82 |
+
margin-left: 0.5rem;
|
83 |
+
}
|
84 |
+
|
85 |
+
.search-bar {
|
86 |
+
position: relative;
|
87 |
+
display: flex;
|
88 |
+
align-items: center;
|
89 |
+
background: rgba(0, 0, 0, 0.3);
|
90 |
+
border: 1px solid rgba(255, 255, 255, 0.2);
|
91 |
+
border-radius: 25px;
|
92 |
+
padding: 0.5rem 1rem;
|
93 |
+
min-width: 300px;
|
94 |
+
transition: all 0.3s ease;
|
95 |
+
}
|
96 |
+
|
97 |
+
.search-bar:focus-within {
|
98 |
+
background: rgba(0, 0, 0, 0.4);
|
99 |
+
border-color: rgba(59, 130, 246, 0.5);
|
100 |
+
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
|
101 |
+
}
|
102 |
+
|
103 |
+
.search-icon {
|
104 |
+
color: rgba(255, 255, 255, 0.6);
|
105 |
+
margin-right: 0.75rem;
|
106 |
+
font-size: 0.9rem;
|
107 |
+
}
|
108 |
+
|
109 |
+
.search-input {
|
110 |
+
background: transparent;
|
111 |
+
border: none;
|
112 |
+
color: var(--text);
|
113 |
+
font-size: 0.9rem;
|
114 |
+
font-weight: 500;
|
115 |
+
width: 100%;
|
116 |
+
outline: none;
|
117 |
+
}
|
118 |
+
|
119 |
+
.search-input::placeholder {
|
120 |
+
color: rgba(255, 255, 255, 0.5);
|
121 |
+
}
|
122 |
+
|
123 |
+
.search-input:focus::placeholder {
|
124 |
+
color: rgba(255, 255, 255, 0.3);
|
125 |
+
}
|
126 |
+
|
127 |
+
/* Responsive search bar */
|
128 |
+
@media (max-width: 768px) {
|
129 |
+
.search-container {
|
130 |
+
margin-left: 0.5rem;
|
131 |
+
}
|
132 |
+
|
133 |
+
.search-bar {
|
134 |
+
min-width: 200px;
|
135 |
+
}
|
136 |
+
}
|
137 |
+
|
138 |
+
@media (max-width: 600px) {
|
139 |
+
.search-container {
|
140 |
+
margin-left: 0.25rem;
|
141 |
+
}
|
142 |
+
|
143 |
+
.search-bar {
|
144 |
+
min-width: 150px;
|
145 |
+
padding: 0.4rem 0.8rem;
|
146 |
+
}
|
147 |
+
}
|
148 |
+
|
149 |
+
.hero { padding: 3.5rem 0 2rem; text-align: center; }
|
150 |
+
.hero h1 { font-size: 2.25rem; font-weight: 800; letter-spacing: -0.02em; }
|
151 |
+
.hero p { color: var(--muted); max-width: 720px; margin: 0.75rem auto 0; }
|
152 |
+
|
153 |
+
.plans { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.5rem; margin: 2.5rem 0 3rem; width: 100%; max-width: 100%; }
|
154 |
+
/* .plans::-webkit-scrollbar { height: 8px; }
|
155 |
+
.plans::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.2); border-radius: 999px; }
|
156 |
+
.plans::-webkit-scrollbar-track { background: rgba(255,255,255,0.06); border-radius: 999px; } */
|
157 |
+
.plan-card { background: rgba(255,255,255,0.03); border: 1px solid rgba(255,255,255,0.06); border-radius: 16px; padding: 2rem; display: flex; flex-direction: column; gap: 1rem; min-height: 100%; width: 100%; }
|
158 |
+
.plan-card .features { flex: 1; gap: 0.75rem; }
|
159 |
+
.plan-card .features li { padding: 0.1rem 0; }
|
160 |
+
.plan-card .cta { margin-top: auto; }
|
161 |
+
|
162 |
+
@media (max-width: 992px) {
|
163 |
+
.plans { grid-template-columns: repeat(2, 1fr); gap: 1.5rem; }
|
164 |
+
}
|
165 |
+
@media (max-width: 600px) {
|
166 |
+
.plans { grid-template-columns: 1fr; gap: 1rem; }
|
167 |
+
.plan-card { padding: 1.5rem; }
|
168 |
+
}
|
169 |
+
|
170 |
+
.plan-title { font-weight: 800; color: var(--text); letter-spacing: -0.01em; }
|
171 |
+
.price { font-size: 2rem; font-weight: 800; }
|
172 |
+
.price small { font-size: 0.9rem; color: var(--muted); font-weight: 600; }
|
173 |
+
.badge { font-size: 0.75rem; color: white; background: linear-gradient(90deg, var(--brand), var(--brand-2)); padding: 0.25rem 0.5rem; border-radius: 999px; display: inline-block; font-weight: 700; }
|
174 |
+
.features { margin-top: 0.5rem; display: grid; gap: 0.5rem; color: var(--text); }
|
175 |
+
.features li { display: flex; align-items: center; gap: 0.5rem; }
|
176 |
+
.features i { color: #10b981; }
|
177 |
+
.cta { margin-top: 0.75rem; display: inline-block; background: linear-gradient(90deg, var(--brand), var(--brand-2)); color: white; text-decoration: none; font-weight: 800; padding: 0.6rem 1rem; border-radius: 10px; text-align: center; }
|
178 |
+
|
179 |
+
.why { margin: 2.5rem 0 3rem; }
|
180 |
+
.why h2 { text-align: center; font-size: 1.5rem; font-weight: 800; margin-bottom: 1rem; }
|
181 |
+
.why-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 1rem; }
|
182 |
+
.why-card { background: rgba(255,255,255,0.03); border: 1px solid rgba(255,255,255,0.06); border-radius: 14px; padding: 1rem; }
|
183 |
+
.why-card h3 { font-weight: 800; margin-bottom: 0.25rem; }
|
184 |
+
.why-card p { color: var(--muted); font-size: 0.95rem; }
|
185 |
+
|
186 |
+
footer { border-top: 1px solid rgba(255,255,255,0.06); padding: 1.5rem 0; color: var(--muted); }
|
187 |
+
|
188 |
+
/* Dropdown Menu Styles */
|
189 |
+
.dropdown {
|
190 |
+
position: relative;
|
191 |
+
}
|
192 |
+
|
193 |
+
.dropdown-toggle {
|
194 |
+
display: flex;
|
195 |
+
align-items: center;
|
196 |
+
gap: 0.5rem;
|
197 |
+
cursor: pointer;
|
198 |
+
}
|
199 |
+
|
200 |
+
.dropdown-toggle i {
|
201 |
+
font-size: 0.8rem;
|
202 |
+
transition: transform 0.2s ease;
|
203 |
+
}
|
204 |
+
|
205 |
+
.dropdown.active .dropdown-toggle i {
|
206 |
+
transform: rotate(180deg);
|
207 |
+
}
|
208 |
+
|
209 |
+
.dropdown-menu {
|
210 |
+
position: absolute;
|
211 |
+
top: 100%;
|
212 |
+
left: 50%;
|
213 |
+
transform: translateX(-50%);
|
214 |
+
background: rgba(15, 23, 42, 0.95);
|
215 |
+
border: 1px solid rgba(255, 255, 255, 0.1);
|
216 |
+
border-radius: 12px;
|
217 |
+
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
|
218 |
+
min-width: 500px;
|
219 |
+
opacity: 0;
|
220 |
+
visibility: hidden;
|
221 |
+
transition: all 0.3s ease;
|
222 |
+
z-index: 1000;
|
223 |
+
margin-top: 1rem;
|
224 |
+
-webkit-backdrop-filter: blur(10px);
|
225 |
+
backdrop-filter: blur(10px);
|
226 |
+
}
|
227 |
+
|
228 |
+
.dropdown.active .dropdown-menu {
|
229 |
+
opacity: 1;
|
230 |
+
visibility: visible;
|
231 |
+
}
|
232 |
+
|
233 |
+
.dropdown-content {
|
234 |
+
display: flex;
|
235 |
+
padding: 2rem;
|
236 |
+
}
|
237 |
+
|
238 |
+
.dropdown-section {
|
239 |
+
flex: 1;
|
240 |
+
}
|
241 |
+
|
242 |
+
.dropdown-section h4 {
|
243 |
+
color: #e2e8f0;
|
244 |
+
font-size: 0.875rem;
|
245 |
+
font-weight: 600;
|
246 |
+
margin: 0 0 1rem 0;
|
247 |
+
text-transform: uppercase;
|
248 |
+
letter-spacing: 0.05em;
|
249 |
+
}
|
250 |
+
|
251 |
+
.dropdown-section ul {
|
252 |
+
list-style: none;
|
253 |
+
margin: 0;
|
254 |
+
padding: 0;
|
255 |
+
}
|
256 |
+
|
257 |
+
.dropdown-section li {
|
258 |
+
margin-bottom: 0.75rem;
|
259 |
+
}
|
260 |
+
|
261 |
+
.dropdown-section a {
|
262 |
+
display: flex;
|
263 |
+
align-items: center;
|
264 |
+
gap: 0.75rem;
|
265 |
+
color: #94a3b8;
|
266 |
+
text-decoration: none;
|
267 |
+
font-size: 0.875rem;
|
268 |
+
padding: 0.5rem;
|
269 |
+
border-radius: 8px;
|
270 |
+
transition: all 0.2s ease;
|
271 |
+
}
|
272 |
+
|
273 |
+
.dropdown-section a:hover {
|
274 |
+
background: rgba(255, 255, 255, 0.1);
|
275 |
+
color: #e2e8f0;
|
276 |
+
}
|
277 |
+
|
278 |
+
.dropdown-section i {
|
279 |
+
font-size: 1rem;
|
280 |
+
width: 20px;
|
281 |
+
text-align: center;
|
282 |
+
}
|
283 |
+
|
284 |
+
.dropdown-divider {
|
285 |
+
width: 1px;
|
286 |
+
background: rgba(255, 255, 255, 0.2);
|
287 |
+
margin: 0 1.5rem;
|
288 |
+
}
|
289 |
+
|
290 |
+
.all-categories {
|
291 |
+
color: #60a5fa !important;
|
292 |
+
font-weight: 500;
|
293 |
+
margin-top: 1rem;
|
294 |
+
display: inline-flex;
|
295 |
+
align-items: center;
|
296 |
+
gap: 0.5rem;
|
297 |
+
}
|
298 |
+
|
299 |
+
.all-categories:hover {
|
300 |
+
background: rgba(59, 130, 246, 0.2) !important;
|
301 |
+
color: #93c5fd !important;
|
302 |
+
}
|
303 |
+
|
304 |
+
.all-categories i {
|
305 |
+
font-size: 0.75rem;
|
306 |
+
transition: transform 0.2s ease;
|
307 |
+
}
|
308 |
+
|
309 |
+
.all-categories:hover i {
|
310 |
+
transform: translateX(3px);
|
311 |
+
}
|
312 |
+
|
313 |
+
/* Responsive dropdown adjustments */
|
314 |
+
@media (max-width: 768px) {
|
315 |
+
.dropdown-menu {
|
316 |
+
min-width: 300px;
|
317 |
+
left: 0;
|
318 |
+
transform: none;
|
319 |
+
}
|
320 |
+
|
321 |
+
.dropdown-content {
|
322 |
+
flex-direction: column;
|
323 |
+
padding: 1.5rem;
|
324 |
+
}
|
325 |
+
|
326 |
+
.dropdown-divider {
|
327 |
+
width: 100%;
|
328 |
+
height: 1px;
|
329 |
+
margin: 1rem 0;
|
330 |
+
}
|
331 |
+
}
|
332 |
+
</style>
|
333 |
+
</head>
|
334 |
+
<body>
|
335 |
+
<header class="header">
|
336 |
+
<nav class="nav">
|
337 |
+
<div class="nav-container">
|
338 |
+
<div class="nav-logo">
|
339 |
+
<i class="fas fa-book-open"></i>
|
340 |
+
<span>booknap</span>
|
341 |
+
</div>
|
342 |
+
<div class="search-container">
|
343 |
+
<div class="search-bar">
|
344 |
+
<i class="fas fa-search search-icon"></i>
|
345 |
+
<input type="text" placeholder="Find a book..." class="search-input">
|
346 |
+
</div>
|
347 |
+
</div>
|
348 |
+
<ul class="nav-menu">
|
349 |
+
<li><a href="books.html" class="nav-link">Home</a></li>
|
350 |
+
<li class="dropdown">
|
351 |
+
<a href="#" class="nav-link dropdown-toggle">Book Summaries <i class="fas fa-chevron-down"></i></a>
|
352 |
+
<div class="dropdown-menu">
|
353 |
+
<div class="dropdown-content">
|
354 |
+
<div class="dropdown-section">
|
355 |
+
<h4>Browse by type</h4>
|
356 |
+
<ul>
|
357 |
+
<li><a href="#"><i class="fas fa-book-open" style="color: #10b981;"></i> Text Summaries</a></li>
|
358 |
+
<li><a href="#"><i class="fas fa-headphones" style="color: #3b82f6;"></i> Audio Summaries</a></li>
|
359 |
+
<li><a href="#"><i class="fas fa-play-circle" style="color: #8b5cf6;"></i> Video Summaries</a></li>
|
360 |
+
<li><a href="#"><i class="fas fa-file-pdf" style="color: #f59e0b;"></i> PDF Downloads</a></li>
|
361 |
+
<li><a href="#"><i class="fas fa-mobile-alt" style="color: #06b6d4;"></i> Mobile App</a></li>
|
362 |
+
</ul>
|
363 |
+
</div>
|
364 |
+
<div class="dropdown-divider"></div>
|
365 |
+
<div class="dropdown-section">
|
366 |
+
<h4>Browse by topic</h4>
|
367 |
+
<ul>
|
368 |
+
<li><a href="#"><i class="fas fa-brain" style="color: #f59e0b;"></i> Psychology</a></li>
|
369 |
+
<li><a href="#"><i class="fas fa-chart-line" style="color: #10b981;"></i> Business</a></li>
|
370 |
+
<li><a href="#"><i class="fas fa-heart" style="color: #ef4444;"></i> Self-Help</a></li>
|
371 |
+
<li><a href="#"><i class="fas fa-graduation-cap" style="color: #8b5cf6;"></i> Education</a></li>
|
372 |
+
<li><a href="#"><i class="fas fa-lightbulb" style="color: #06b6d4;"></i> Innovation</a></li>
|
373 |
+
</ul>
|
374 |
+
<a href="#" class="all-categories">all categories <i class="fas fa-arrow-right"></i></a>
|
375 |
+
</div>
|
376 |
+
</div>
|
377 |
+
</div>
|
378 |
+
</li>
|
379 |
+
<li><a href="pricing.html" class="nav-link active">Pricing</a></li>
|
380 |
+
<li><a href="blog.html" class="nav-link">Blog</a></li>
|
381 |
+
</ul>
|
382 |
+
<div class="nav-login">
|
383 |
+
<a href="login.html" class="login-btn">Login</a>
|
384 |
+
<a href="signup.html" class="signup-btn">Sign Up</a>
|
385 |
+
</div>
|
386 |
+
<div class="nav-toggle">
|
387 |
+
<span></span>
|
388 |
+
<span></span>
|
389 |
+
<span></span>
|
390 |
+
</div>
|
391 |
+
</div>
|
392 |
+
</nav>
|
393 |
+
</header>
|
394 |
+
|
395 |
+
<main>
|
396 |
+
<section class="hero container">
|
397 |
+
<h1>You're ready to grow! We're here to help.</h1>
|
398 |
+
<p>booknap helps you achieve your goals efficiently with bite-sized book summaries.</p>
|
399 |
+
</section>
|
400 |
+
|
401 |
+
<section class="plans container">
|
402 |
+
<article class="plan-card">
|
403 |
+
<div class="plan-title">FREE</div>
|
404 |
+
<div class="price">$0 <small>/ forever</small></div>
|
405 |
+
<ul class="features">
|
406 |
+
<li><i class="fas fa-check-circle"></i> Get access to 2 free summaries</li>
|
407 |
+
</ul>
|
408 |
+
<a class="cta" href="#">Get Started</a>
|
409 |
+
</article>
|
410 |
+
|
411 |
+
<article class="plan-card">
|
412 |
+
<div class="plan-title">Premium Weekly</div>
|
413 |
+
<div class="price">$4.99 <small>/ week</small></div>
|
414 |
+
<ul class="features">
|
415 |
+
<li><i class="fas fa-check-circle"></i> All Premium features</li>
|
416 |
+
<li><i class="fas fa-check-circle"></i> Cancel anytime</li>
|
417 |
+
<li><i class="fas fa-check-circle"></i> Best for short-term goals</li>
|
418 |
+
</ul>
|
419 |
+
<a class="cta" href="#">Buy Now</a>
|
420 |
+
</article>
|
421 |
+
|
422 |
+
<article class="plan-card">
|
423 |
+
<div class="badge">Best Value</div>
|
424 |
+
<div class="plan-title">Premium Yearly</div>
|
425 |
+
<div class="price">$49 <small>/ year</small></div>
|
426 |
+
<ul class="features">
|
427 |
+
<li><i class="fas fa-check-circle"></i> Text, audio, and visual summaries</li>
|
428 |
+
<li><i class="fas fa-check-circle"></i> Visual book summaries</li>
|
429 |
+
<li><i class="fas fa-check-circle"></i> PDF downloads</li>
|
430 |
+
<li><i class="fas fa-check-circle"></i> Mobile app</li>
|
431 |
+
<li><i class="fas fa-check-circle"></i> Download offline</li>
|
432 |
+
<li><i class="fas fa-check-circle"></i> Audio narrations</li>
|
433 |
+
<li><i class="fas fa-check-circle"></i> Quizzes</li>
|
434 |
+
<li><i class="fas fa-check-circle"></i> Sync with Kindle</li>
|
435 |
+
<li><i class="fas fa-check-circle"></i> New content weekly</li>
|
436 |
+
<li><i class="fas fa-check-circle"></i> Cancel anytime</li>
|
437 |
+
</ul>
|
438 |
+
<a class="cta" href="#">Buy Now</a>
|
439 |
+
</article>
|
440 |
+
|
441 |
+
<article class="plan-card">
|
442 |
+
<div class="plan-title">Premium Monthly</div>
|
443 |
+
<div class="price">$12.99 <small>/ month</small></div>
|
444 |
+
<ul class="features">
|
445 |
+
<li><i class="fas fa-check-circle"></i> Text, audio, and visual summaries</li>
|
446 |
+
<li><i class="fas fa-check-circle"></i> Visual book summaries</li>
|
447 |
+
<li><i class="fas fa-check-circle"></i> PDF downloads</li>
|
448 |
+
<li><i class="fas fa-check-circle"></i> Mobile app</li>
|
449 |
+
<li><i class="fas fa-check-circle"></i> Download offline</li>
|
450 |
+
<li><i class="fas fa-check-circle"></i> Audio narrations</li>
|
451 |
+
<li><i class="fas fa-check-circle"></i> Quizzes</li>
|
452 |
+
<li><i class="fas fa-check-circle"></i> Sync with Kindle</li>
|
453 |
+
<li><i class="fas fa-check-circle"></i> New content weekly</li>
|
454 |
+
<li><i class="fas fa-check-circle"></i> Cancel anytime</li>
|
455 |
+
</ul>
|
456 |
+
<a class="cta" href="#">Buy Now</a>
|
457 |
+
</article>
|
458 |
+
</section>
|
459 |
+
|
460 |
+
<section class="why container">
|
461 |
+
<h2>Not Sure Yet? Hereβs Why booknap Is Worth It</h2>
|
462 |
+
<div class="why-grid">
|
463 |
+
<div class="why-card">
|
464 |
+
<h3>High-Quality Titles</h3>
|
465 |
+
<p>Our summaries are unbiased, concise, and comprehensive, giving you the most valuable insights fast.</p>
|
466 |
+
</div>
|
467 |
+
<div class="why-card">
|
468 |
+
<h3>New content added constantly</h3>
|
469 |
+
<p>We add new content weekly, including bestsellers.</p>
|
470 |
+
</div>
|
471 |
+
<div class="why-card">
|
472 |
+
<h3>Learn on the go</h3>
|
473 |
+
<p>Read or listen anywhereβiOS, tablet, laptop, and Kindle.</p>
|
474 |
+
</div>
|
475 |
+
<div class="why-card">
|
476 |
+
<h3>Cancel anytime</h3>
|
477 |
+
<p>Changed your mind? Cancel your subscription anytime.</p>
|
478 |
+
</div>
|
479 |
+
</div>
|
480 |
+
</section>
|
481 |
+
</main>
|
482 |
+
|
483 |
+
<footer>
|
484 |
+
<div class="container">
|
485 |
+
<p>© 2025 booknap. All rights reserved.</p>
|
486 |
+
</div>
|
487 |
+
</footer>
|
488 |
+
|
489 |
+
<script>
|
490 |
+
// Book Summaries dropdown functionality - same as home page but click-based
|
491 |
+
document.addEventListener('DOMContentLoaded', function() {
|
492 |
+
const dropdownToggle = document.querySelector('.dropdown-toggle');
|
493 |
+
const dropdown = document.querySelector('.dropdown');
|
494 |
+
|
495 |
+
if (dropdownToggle && dropdown) {
|
496 |
+
// Toggle dropdown on click (instead of hover)
|
497 |
+
dropdownToggle.addEventListener('click', function(e) {
|
498 |
+
e.preventDefault();
|
499 |
+
|
500 |
+
// Toggle the active class on the dropdown container
|
501 |
+
dropdown.classList.toggle('active');
|
502 |
+
});
|
503 |
+
|
504 |
+
// Close dropdown when clicking outside
|
505 |
+
document.addEventListener('click', function(e) {
|
506 |
+
if (!dropdown.contains(e.target)) {
|
507 |
+
dropdown.classList.remove('active');
|
508 |
+
}
|
509 |
+
});
|
510 |
+
|
511 |
+
// Close dropdown when pressing Escape key
|
512 |
+
document.addEventListener('keydown', function(e) {
|
513 |
+
if (e.key === 'Escape') {
|
514 |
+
dropdown.classList.remove('active');
|
515 |
+
}
|
516 |
+
});
|
517 |
+
}
|
518 |
+
});
|
519 |
+
</script>
|
520 |
+
</body>
|
521 |
+
</html>
|
booknap project/requirements.txt
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
flask==2.3.3
|
2 |
+
kagglehub[pandas-datasets]==0.1.0
|
3 |
+
pandas==2.0.3
|
4 |
+
requests==2.31.0
|
5 |
+
SQLAlchemy==2.0.30
|
6 |
+
psycopg2-binary==2.9.9
|
7 |
+
flask-cors==4.0.0
|
8 |
+
|
booknap project/script.js
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
|
booknap project/setup_database.py
ADDED
@@ -0,0 +1,102 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/env python3
|
2 |
+
"""
|
3 |
+
Database setup script for Booknap
|
4 |
+
Run this script to create the necessary database tables
|
5 |
+
"""
|
6 |
+
|
7 |
+
import os
|
8 |
+
from sqlalchemy import create_engine, text
|
9 |
+
from sqlalchemy.exc import SQLAlchemyError
|
10 |
+
|
11 |
+
def setup_database():
|
12 |
+
"""Set up the database schema"""
|
13 |
+
|
14 |
+
# Database configuration - update with your actual password
|
15 |
+
DATABASE_URL = os.environ.get(
|
16 |
+
"DATABASE_URL",
|
17 |
+
"postgresql://postgres:YOUR_ACTUAL_PASSWORD@db.ckrqyjfdifjbsuuofegd.supabase.co:5432/postgres"
|
18 |
+
)
|
19 |
+
|
20 |
+
print("Connecting to database...")
|
21 |
+
print(f"URL: {DATABASE_URL.replace('YOUR_ACTUAL_PASSWORD', '***')}")
|
22 |
+
|
23 |
+
try:
|
24 |
+
# Create engine
|
25 |
+
engine = create_engine(DATABASE_URL, pool_pre_ping=True)
|
26 |
+
|
27 |
+
# Test connection
|
28 |
+
with engine.connect() as conn:
|
29 |
+
print("β
Database connection successful!")
|
30 |
+
|
31 |
+
# Create users table
|
32 |
+
create_users_table = """
|
33 |
+
CREATE TABLE IF NOT EXISTS users (
|
34 |
+
id SERIAL PRIMARY KEY,
|
35 |
+
full_name VARCHAR(255) NOT NULL,
|
36 |
+
email VARCHAR(255) UNIQUE NOT NULL,
|
37 |
+
password VARCHAR(255) NOT NULL,
|
38 |
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
39 |
+
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
40 |
+
);
|
41 |
+
"""
|
42 |
+
|
43 |
+
# Create index
|
44 |
+
create_index = """
|
45 |
+
CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);
|
46 |
+
"""
|
47 |
+
|
48 |
+
# Execute schema creation
|
49 |
+
print("Creating users table...")
|
50 |
+
conn.execute(text(create_users_table))
|
51 |
+
|
52 |
+
print("Creating email index...")
|
53 |
+
conn.execute(text(create_index))
|
54 |
+
|
55 |
+
# Commit changes
|
56 |
+
conn.commit()
|
57 |
+
|
58 |
+
print("β
Database schema created successfully!")
|
59 |
+
|
60 |
+
# Verify table exists
|
61 |
+
result = conn.execute(text("SELECT table_name FROM information_schema.tables WHERE table_name = 'users'"))
|
62 |
+
if result.fetchone():
|
63 |
+
print("β
Users table verified!")
|
64 |
+
|
65 |
+
# Show table structure
|
66 |
+
result = conn.execute(text("\\d users"))
|
67 |
+
print("\nTable structure:")
|
68 |
+
# Note: \d command won't work in Python, let's use a different approach
|
69 |
+
result = conn.execute(text("SELECT column_name, data_type, is_nullable FROM information_schema.columns WHERE table_name = 'users' ORDER BY ordinal_position"))
|
70 |
+
columns = result.fetchall()
|
71 |
+
for col in columns:
|
72 |
+
print(f" {col[0]}: {col[1]} ({'NULL' if col[2] == 'YES' else 'NOT NULL'})")
|
73 |
+
|
74 |
+
else:
|
75 |
+
print("β Users table not found!")
|
76 |
+
|
77 |
+
except SQLAlchemyError as e:
|
78 |
+
print(f"β Database error: {e}")
|
79 |
+
print("\nPlease check:")
|
80 |
+
print("1. Your database password is correct")
|
81 |
+
print("2. The database is accessible from your network")
|
82 |
+
print("3. Update the DATABASE_URL in this script or set the environment variable")
|
83 |
+
|
84 |
+
except Exception as e:
|
85 |
+
print(f"β Unexpected error: {e}")
|
86 |
+
|
87 |
+
if __name__ == "__main__":
|
88 |
+
print("π Booknap Database Setup")
|
89 |
+
print("=" * 40)
|
90 |
+
|
91 |
+
# Check if DATABASE_URL is set
|
92 |
+
if not os.environ.get("DATABASE_URL"):
|
93 |
+
print("β οΈ DATABASE_URL environment variable not set")
|
94 |
+
print("Please set it with your actual database password:")
|
95 |
+
print("export DATABASE_URL='postgresql://postgres:YOUR_PASSWORD@db.ckrqyjfdifjbsuuofegd.supabase.co:5432/postgres'")
|
96 |
+
print()
|
97 |
+
|
98 |
+
setup_database()
|
99 |
+
|
100 |
+
print("\n" + "=" * 40)
|
101 |
+
print("Setup complete!")
|
102 |
+
|
booknap project/signup.html
ADDED
@@ -0,0 +1,371 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8">
|
5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6 |
+
<title>Create Account - Booknap</title>
|
7 |
+
<style>
|
8 |
+
* {
|
9 |
+
margin: 0;
|
10 |
+
padding: 0;
|
11 |
+
box-sizing: border-box;
|
12 |
+
}
|
13 |
+
|
14 |
+
body {
|
15 |
+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
16 |
+
background: linear-gradient(180deg, #0b1020, #0b1022 30%, #0b1124);
|
17 |
+
min-height: 100vh;
|
18 |
+
display: flex;
|
19 |
+
align-items: center;
|
20 |
+
justify-content: center;
|
21 |
+
color: white;
|
22 |
+
}
|
23 |
+
|
24 |
+
.signup-container {
|
25 |
+
width: 100%;
|
26 |
+
max-width: 520px;
|
27 |
+
padding: 20px;
|
28 |
+
}
|
29 |
+
|
30 |
+
.signup-card {
|
31 |
+
background: rgba(255,255,255,0.04);
|
32 |
+
-webkit-backdrop-filter: blur(10px);
|
33 |
+
backdrop-filter: blur(10px);
|
34 |
+
border: 1px solid rgba(255,255,255,0.08);
|
35 |
+
border-radius: 16px;
|
36 |
+
padding: 40px;
|
37 |
+
box-shadow: 0 16px 40px rgba(0,0,0,0.12);
|
38 |
+
text-align: center;
|
39 |
+
}
|
40 |
+
|
41 |
+
.signup-card h2 {
|
42 |
+
color: white;
|
43 |
+
margin-bottom: 10px;
|
44 |
+
font-size: 32px;
|
45 |
+
font-weight: 700;
|
46 |
+
}
|
47 |
+
|
48 |
+
.signup-subtitle {
|
49 |
+
color: #cbd5e1;
|
50 |
+
margin-bottom: 30px;
|
51 |
+
font-size: 16px;
|
52 |
+
font-weight: 400;
|
53 |
+
}
|
54 |
+
|
55 |
+
.input-group {
|
56 |
+
margin-bottom: 20px;
|
57 |
+
text-align: left;
|
58 |
+
}
|
59 |
+
|
60 |
+
.input-group label {
|
61 |
+
display: block;
|
62 |
+
margin-bottom: 8px;
|
63 |
+
color: white;
|
64 |
+
font-weight: 500;
|
65 |
+
font-size: 14px;
|
66 |
+
}
|
67 |
+
|
68 |
+
.input-group input {
|
69 |
+
width: 100%;
|
70 |
+
padding: 0.75rem 0.9rem;
|
71 |
+
border: 1px solid rgba(255,255,255,0.12);
|
72 |
+
border-radius: 10px;
|
73 |
+
font-size: 16px;
|
74 |
+
transition: all 0.3s ease;
|
75 |
+
background: rgba(15,23,42,0.7);
|
76 |
+
color: white;
|
77 |
+
}
|
78 |
+
|
79 |
+
.input-group input:focus {
|
80 |
+
outline: none;
|
81 |
+
border-color: rgba(59,130,246,0.55);
|
82 |
+
background: rgba(15,23,42,0.7);
|
83 |
+
box-shadow: 0 0 0 3px rgba(59,130,246,0.15);
|
84 |
+
}
|
85 |
+
|
86 |
+
.input-group input::placeholder {
|
87 |
+
color: #94a3b8;
|
88 |
+
}
|
89 |
+
|
90 |
+
.checkbox-group {
|
91 |
+
display: flex;
|
92 |
+
align-items: center;
|
93 |
+
justify-content: space-between;
|
94 |
+
margin: 20px 0;
|
95 |
+
font-size: 14px;
|
96 |
+
}
|
97 |
+
|
98 |
+
.checkbox-wrapper {
|
99 |
+
display: flex;
|
100 |
+
align-items: center;
|
101 |
+
gap: 8px;
|
102 |
+
}
|
103 |
+
|
104 |
+
.checkbox-wrapper input[type="checkbox"] {
|
105 |
+
width: 18px;
|
106 |
+
height: 18px;
|
107 |
+
accent-color: #3b82f6;
|
108 |
+
}
|
109 |
+
|
110 |
+
.checkbox-wrapper label {
|
111 |
+
color: white;
|
112 |
+
cursor: pointer;
|
113 |
+
}
|
114 |
+
|
115 |
+
.terms-link {
|
116 |
+
color: #93c5fd;
|
117 |
+
text-decoration: none;
|
118 |
+
}
|
119 |
+
|
120 |
+
.terms-link:hover {
|
121 |
+
text-decoration: underline;
|
122 |
+
}
|
123 |
+
|
124 |
+
.signup-submit-btn {
|
125 |
+
width: 100%;
|
126 |
+
padding: 0.85rem 1rem;
|
127 |
+
background: linear-gradient(90deg, #3b82f6, #6366f1);
|
128 |
+
color: white;
|
129 |
+
border: none;
|
130 |
+
border-radius: 12px;
|
131 |
+
font-size: 16px;
|
132 |
+
font-weight: 600;
|
133 |
+
cursor: pointer;
|
134 |
+
transition: all 0.3s ease;
|
135 |
+
margin: 20px 0;
|
136 |
+
}
|
137 |
+
|
138 |
+
.signup-submit-btn:hover {
|
139 |
+
transform: translateY(-2px);
|
140 |
+
box-shadow: 0 10px 25px rgba(59, 130, 246, 0.3);
|
141 |
+
}
|
142 |
+
|
143 |
+
.divider {
|
144 |
+
display: flex;
|
145 |
+
align-items: center;
|
146 |
+
margin: 25px 0;
|
147 |
+
color: #94a3b8;
|
148 |
+
font-size: 14px;
|
149 |
+
}
|
150 |
+
|
151 |
+
.divider::before,
|
152 |
+
.divider::after {
|
153 |
+
content: '';
|
154 |
+
flex: 1;
|
155 |
+
height: 1px;
|
156 |
+
background: rgba(255,255,255,0.15);
|
157 |
+
}
|
158 |
+
|
159 |
+
.divider span {
|
160 |
+
padding: 0 15px;
|
161 |
+
}
|
162 |
+
|
163 |
+
.google-btn {
|
164 |
+
width: 100%;
|
165 |
+
padding: 0.75rem 1rem;
|
166 |
+
background: rgba(255,255,255,0.06);
|
167 |
+
color: white;
|
168 |
+
border: 1px solid rgba(255,255,255,0.12);
|
169 |
+
border-radius: 10px;
|
170 |
+
font-size: 16px;
|
171 |
+
font-weight: 500;
|
172 |
+
cursor: pointer;
|
173 |
+
transition: all 0.3s ease;
|
174 |
+
display: flex;
|
175 |
+
align-items: center;
|
176 |
+
justify-content: center;
|
177 |
+
gap: 10px;
|
178 |
+
}
|
179 |
+
|
180 |
+
.google-btn:hover {
|
181 |
+
background: rgba(255,255,255,0.08);
|
182 |
+
border-color: rgba(255,255,255,0.2);
|
183 |
+
}
|
184 |
+
|
185 |
+
.google-icon {
|
186 |
+
width: 20px;
|
187 |
+
height: 20px;
|
188 |
+
background: white;
|
189 |
+
border-radius: 50%;
|
190 |
+
display: flex;
|
191 |
+
align-items: center;
|
192 |
+
justify-content: center;
|
193 |
+
font-weight: bold;
|
194 |
+
color: #1f2937;
|
195 |
+
font-size: 14px;
|
196 |
+
}
|
197 |
+
|
198 |
+
.login-link {
|
199 |
+
margin-top: 25px;
|
200 |
+
color: #94a3b8;
|
201 |
+
font-size: 14px;
|
202 |
+
}
|
203 |
+
|
204 |
+
.login-link a {
|
205 |
+
color: #93c5fd;
|
206 |
+
text-decoration: none;
|
207 |
+
font-weight: 600;
|
208 |
+
}
|
209 |
+
|
210 |
+
.login-link a:hover {
|
211 |
+
text-decoration: underline;
|
212 |
+
}
|
213 |
+
|
214 |
+
.error-message {
|
215 |
+
background: rgba(239, 68, 68, 0.1);
|
216 |
+
color: #fca5a5;
|
217 |
+
padding: 12px;
|
218 |
+
border-radius: 8px;
|
219 |
+
margin-bottom: 20px;
|
220 |
+
font-size: 14px;
|
221 |
+
display: none;
|
222 |
+
border: 1px solid rgba(239, 68, 68, 0.2);
|
223 |
+
}
|
224 |
+
|
225 |
+
.success-message {
|
226 |
+
background: rgba(34, 197, 94, 0.1);
|
227 |
+
color: #86efac;
|
228 |
+
padding: 12px;
|
229 |
+
border-radius: 8px;
|
230 |
+
margin-bottom: 20px;
|
231 |
+
font-size: 14px;
|
232 |
+
display: none;
|
233 |
+
border: 1px solid rgba(34, 197, 94, 0.2);
|
234 |
+
}
|
235 |
+
|
236 |
+
@media (max-width: 480px) {
|
237 |
+
.signup-card {
|
238 |
+
padding: 30px 20px;
|
239 |
+
}
|
240 |
+
|
241 |
+
.signup-card h2 {
|
242 |
+
font-size: 28px;
|
243 |
+
}
|
244 |
+
}
|
245 |
+
</style>
|
246 |
+
</head>
|
247 |
+
<body>
|
248 |
+
<main class="signup-container">
|
249 |
+
<div class="signup-card">
|
250 |
+
<h2>Join Booknap</h2>
|
251 |
+
<p class="signup-subtitle">Create your account to start your reading journey</p>
|
252 |
+
|
253 |
+
<div id="errorMessage" class="error-message"></div>
|
254 |
+
<div id="successMessage" class="success-message"></div>
|
255 |
+
|
256 |
+
<form id="signupForm">
|
257 |
+
<div class="input-group">
|
258 |
+
<label for="fullName">Full Name</label>
|
259 |
+
<input type="text" id="fullName" name="fullName" placeholder="Enter your full name" required>
|
260 |
+
</div>
|
261 |
+
<div class="input-group">
|
262 |
+
<label for="email">Email</label>
|
263 |
+
<input type="email" id="email" name="email" placeholder="Enter your email address" required>
|
264 |
+
</div>
|
265 |
+
<div class="input-group">
|
266 |
+
<label for="password">Password</label>
|
267 |
+
<input type="password" id="password" name="password" placeholder="Create a strong password" required>
|
268 |
+
</div>
|
269 |
+
<div class="input-group">
|
270 |
+
<label for="confirmPassword">Confirm Password</label>
|
271 |
+
<input type="password" id="confirmPassword" name="confirmPassword" placeholder="Confirm your password" required>
|
272 |
+
</div>
|
273 |
+
|
274 |
+
<div class="checkbox-group">
|
275 |
+
<div class="checkbox-wrapper">
|
276 |
+
<input type="checkbox" id="agreeTerms" name="agreeTerms" required>
|
277 |
+
<label for="agreeTerms">I agree to the <a href="#" class="terms-link">Terms of Service</a></label>
|
278 |
+
</div>
|
279 |
+
</div>
|
280 |
+
|
281 |
+
<button type="submit" class="signup-submit-btn">Create Account</button>
|
282 |
+
</form>
|
283 |
+
|
284 |
+
<div class="divider">
|
285 |
+
<span>or</span>
|
286 |
+
</div>
|
287 |
+
|
288 |
+
<button class="google-btn">
|
289 |
+
<div class="google-icon">G</div>
|
290 |
+
Continue with Google
|
291 |
+
</button>
|
292 |
+
|
293 |
+
<p class="login-link">Already have an account? <a href="login.html">Sign in</a></p>
|
294 |
+
</div>
|
295 |
+
|
296 |
+
|
297 |
+
</main>
|
298 |
+
|
299 |
+
<script>
|
300 |
+
document.getElementById('signupForm').addEventListener('submit', async function(event) {
|
301 |
+
event.preventDefault();
|
302 |
+
|
303 |
+
const fullName = document.getElementById('fullName').value;
|
304 |
+
const email = document.getElementById('email').value;
|
305 |
+
const password = document.getElementById('password').value;
|
306 |
+
const confirmPassword = document.getElementById('confirmPassword').value;
|
307 |
+
const agreeTerms = document.getElementById('agreeTerms').checked;
|
308 |
+
|
309 |
+
// Hide previous messages
|
310 |
+
document.getElementById('errorMessage').style.display = 'none';
|
311 |
+
document.getElementById('successMessage').style.display = 'none';
|
312 |
+
|
313 |
+
// Basic validation
|
314 |
+
if (!agreeTerms) {
|
315 |
+
showMessage('Please agree to the Terms of Service', 'error');
|
316 |
+
return;
|
317 |
+
}
|
318 |
+
|
319 |
+
if (password !== confirmPassword) {
|
320 |
+
showMessage('Passwords do not match', 'error');
|
321 |
+
return;
|
322 |
+
}
|
323 |
+
|
324 |
+
if (password.length < 6) {
|
325 |
+
showMessage('Password must be at least 6 characters long', 'error');
|
326 |
+
return;
|
327 |
+
}
|
328 |
+
|
329 |
+
try {
|
330 |
+
const response = await fetch('/signup', {
|
331 |
+
method: 'POST',
|
332 |
+
headers: {
|
333 |
+
'Content-Type': 'application/json',
|
334 |
+
},
|
335 |
+
body: JSON.stringify({ fullName, email, password }),
|
336 |
+
});
|
337 |
+
|
338 |
+
const data = await response.json();
|
339 |
+
|
340 |
+
if (response.ok) {
|
341 |
+
showMessage(data.message, 'success');
|
342 |
+
// Redirect to login page after successful signup
|
343 |
+
setTimeout(() => {
|
344 |
+
window.location.href = 'login.html';
|
345 |
+
}, 2000);
|
346 |
+
} else {
|
347 |
+
showMessage(data.error, 'error');
|
348 |
+
}
|
349 |
+
} catch (error) {
|
350 |
+
showMessage('An error occurred. Please try again.', 'error');
|
351 |
+
}
|
352 |
+
});
|
353 |
+
|
354 |
+
function showMessage(message, type) {
|
355 |
+
const errorDiv = document.getElementById('errorMessage');
|
356 |
+
const successDiv = document.getElementById('successMessage');
|
357 |
+
|
358 |
+
if (type === 'error') {
|
359 |
+
errorDiv.textContent = message;
|
360 |
+
errorDiv.style.display = 'block';
|
361 |
+
successDiv.style.display = 'none';
|
362 |
+
} else {
|
363 |
+
successDiv.textContent = message;
|
364 |
+
successDiv.style.display = 'block';
|
365 |
+
errorDiv.style.display = 'none';
|
366 |
+
}
|
367 |
+
}
|
368 |
+
</script>
|
369 |
+
</body>
|
370 |
+
</html>
|
371 |
+
|
booknap project/static-blog.html
ADDED
@@ -0,0 +1,222 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8">
|
5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6 |
+
<title>Blog with Static Dataset</title>
|
7 |
+
<style>
|
8 |
+
body {
|
9 |
+
font-family: 'Inter', sans-serif;
|
10 |
+
background: linear-gradient(180deg, #0b1020, #0b1022 30%, #0b1124);
|
11 |
+
color: #e2e8f0;
|
12 |
+
margin: 0;
|
13 |
+
padding: 20px;
|
14 |
+
}
|
15 |
+
|
16 |
+
.container {
|
17 |
+
max-width: 1200px;
|
18 |
+
margin: 0 auto;
|
19 |
+
}
|
20 |
+
|
21 |
+
.blog-grid {
|
22 |
+
display: grid;
|
23 |
+
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
|
24 |
+
gap: 2rem;
|
25 |
+
margin-top: 2rem;
|
26 |
+
}
|
27 |
+
|
28 |
+
.blog-card {
|
29 |
+
background: rgba(255, 255, 255, 0.05);
|
30 |
+
border-radius: 16px;
|
31 |
+
overflow: hidden;
|
32 |
+
border: 1px solid rgba(255, 255, 255, 0.1);
|
33 |
+
transition: transform 0.3s ease;
|
34 |
+
}
|
35 |
+
|
36 |
+
.blog-card:hover {
|
37 |
+
transform: translateY(-8px);
|
38 |
+
}
|
39 |
+
|
40 |
+
.blog-card-image {
|
41 |
+
width: 100%;
|
42 |
+
height: 200px;
|
43 |
+
background-size: cover;
|
44 |
+
background-position: center;
|
45 |
+
}
|
46 |
+
|
47 |
+
.blog-card-content {
|
48 |
+
padding: 1.5rem;
|
49 |
+
}
|
50 |
+
|
51 |
+
.blog-card-title {
|
52 |
+
font-size: 1.25rem;
|
53 |
+
font-weight: 600;
|
54 |
+
margin-bottom: 0.5rem;
|
55 |
+
}
|
56 |
+
|
57 |
+
.blog-card-date {
|
58 |
+
color: #94a3b8;
|
59 |
+
font-size: 0.875rem;
|
60 |
+
margin-bottom: 1rem;
|
61 |
+
}
|
62 |
+
|
63 |
+
.blog-card-link {
|
64 |
+
color: #8b5cf6;
|
65 |
+
text-decoration: none;
|
66 |
+
font-weight: 600;
|
67 |
+
font-size: 0.875rem;
|
68 |
+
text-transform: uppercase;
|
69 |
+
}
|
70 |
+
|
71 |
+
.search-bar {
|
72 |
+
background: rgba(255, 255, 255, 0.1);
|
73 |
+
border: 1px solid rgba(255, 255, 255, 0.2);
|
74 |
+
border-radius: 25px;
|
75 |
+
padding: 0.75rem 1.5rem;
|
76 |
+
color: #e2e8f0;
|
77 |
+
width: 100%;
|
78 |
+
max-width: 400px;
|
79 |
+
margin: 2rem auto;
|
80 |
+
display: block;
|
81 |
+
}
|
82 |
+
|
83 |
+
.search-bar::placeholder {
|
84 |
+
color: #94a3b8;
|
85 |
+
}
|
86 |
+
</style>
|
87 |
+
</head>
|
88 |
+
<body>
|
89 |
+
<div class="container">
|
90 |
+
<h1>Blog with Dataset Integration</h1>
|
91 |
+
|
92 |
+
<input type="text" class="search-bar" placeholder="Search articles..." id="searchInput">
|
93 |
+
|
94 |
+
<div class="blog-grid" id="blogGrid">
|
95 |
+
<!-- Articles will be loaded here -->
|
96 |
+
</div>
|
97 |
+
</div>
|
98 |
+
|
99 |
+
<script>
|
100 |
+
// Static dataset - you can replace this with your own data
|
101 |
+
const newsDataset = [
|
102 |
+
{
|
103 |
+
title: "The Future of Artificial Intelligence in 2024",
|
104 |
+
description: "Exploring the latest developments in AI technology and their impact on various industries.",
|
105 |
+
date: "2024-01-15",
|
106 |
+
source: "Tech News",
|
107 |
+
category: "Technology",
|
108 |
+
image: "https://images.unsplash.com/photo-1485827404703-89b55fcc595e?w=500"
|
109 |
+
},
|
110 |
+
{
|
111 |
+
title: "Sustainable Business Practices That Drive Growth",
|
112 |
+
description: "How companies are implementing eco-friendly strategies while maintaining profitability.",
|
113 |
+
date: "2024-01-14",
|
114 |
+
source: "Business Weekly",
|
115 |
+
category: "Business",
|
116 |
+
image: "https://images.unsplash.com/photo-1554224155-6726b3ff858f?w=500"
|
117 |
+
},
|
118 |
+
{
|
119 |
+
title: "Mental Health Awareness in the Digital Age",
|
120 |
+
description: "Understanding the impact of social media and technology on mental well-being.",
|
121 |
+
date: "2024-01-13",
|
122 |
+
source: "Health Journal",
|
123 |
+
category: "Health",
|
124 |
+
image: "https://images.unsplash.com/photo-1573496359142-b8d87734a5a2?w=500"
|
125 |
+
},
|
126 |
+
{
|
127 |
+
title: "Climate Change Solutions: What Works",
|
128 |
+
description: "Evidence-based approaches to addressing climate change at individual and corporate levels.",
|
129 |
+
date: "2024-01-12",
|
130 |
+
source: "Environmental Times",
|
131 |
+
category: "Environment",
|
132 |
+
image: "https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=500"
|
133 |
+
},
|
134 |
+
{
|
135 |
+
title: "The Rise of Remote Work Culture",
|
136 |
+
description: "How remote work is reshaping company culture and employee expectations.",
|
137 |
+
date: "2024-01-11",
|
138 |
+
source: "Workplace Insights",
|
139 |
+
category: "Work",
|
140 |
+
image: "https://images.unsplash.com/photo-1522202176988-66273c2fd55f?w=500"
|
141 |
+
},
|
142 |
+
{
|
143 |
+
title: "Digital Privacy in the Age of Big Data",
|
144 |
+
description: "Protecting personal information in an increasingly connected world.",
|
145 |
+
date: "2024-01-10",
|
146 |
+
source: "Privacy Today",
|
147 |
+
category: "Technology",
|
148 |
+
image: "https://images.unsplash.com/photo-1544716278-ca5e3f4abd8c?w=500"
|
149 |
+
}
|
150 |
+
];
|
151 |
+
|
152 |
+
// Function to create article cards
|
153 |
+
function createArticleCard(article) {
|
154 |
+
return `
|
155 |
+
<article class="blog-card">
|
156 |
+
<div class="blog-card-image" style="background-image: url('${article.image}');"></div>
|
157 |
+
<div class="blog-card-content">
|
158 |
+
<h3 class="blog-card-title">${article.title}</h3>
|
159 |
+
<p class="blog-card-date">${article.date} β’ ${article.source} β’ ${article.category}</p>
|
160 |
+
<p style="color: #94a3b8; font-size: 0.875rem; margin-bottom: 1rem;">${article.description}</p>
|
161 |
+
<a href="#" class="blog-card-link">READ MORE</a>
|
162 |
+
</div>
|
163 |
+
</article>
|
164 |
+
`;
|
165 |
+
}
|
166 |
+
|
167 |
+
// Function to display articles
|
168 |
+
function displayArticles(articles) {
|
169 |
+
const blogGrid = document.getElementById('blogGrid');
|
170 |
+
blogGrid.innerHTML = articles.map(createArticleCard).join('');
|
171 |
+
}
|
172 |
+
|
173 |
+
// Function to filter articles
|
174 |
+
function filterArticles(searchTerm) {
|
175 |
+
const filtered = newsDataset.filter(article =>
|
176 |
+
article.title.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
177 |
+
article.description.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
178 |
+
article.category.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
179 |
+
article.source.toLowerCase().includes(searchTerm.toLowerCase())
|
180 |
+
);
|
181 |
+
displayArticles(filtered);
|
182 |
+
}
|
183 |
+
|
184 |
+
// Initialize the page
|
185 |
+
document.addEventListener('DOMContentLoaded', function() {
|
186 |
+
// Display all articles initially
|
187 |
+
displayArticles(newsDataset);
|
188 |
+
|
189 |
+
// Add search functionality
|
190 |
+
const searchInput = document.getElementById('searchInput');
|
191 |
+
searchInput.addEventListener('input', function(e) {
|
192 |
+
filterArticles(e.target.value);
|
193 |
+
});
|
194 |
+
});
|
195 |
+
|
196 |
+
// Example: Add new article to dataset
|
197 |
+
function addNewArticle(article) {
|
198 |
+
newsDataset.push(article);
|
199 |
+
displayArticles(newsDataset);
|
200 |
+
}
|
201 |
+
|
202 |
+
// Example: Get articles by category
|
203 |
+
function getArticlesByCategory(category) {
|
204 |
+
return newsDataset.filter(article => article.category === category);
|
205 |
+
}
|
206 |
+
|
207 |
+
// Example: Get latest articles
|
208 |
+
function getLatestArticles(count = 3) {
|
209 |
+
return newsDataset
|
210 |
+
.sort((a, b) => new Date(b.date) - new Date(a.date))
|
211 |
+
.slice(0, count);
|
212 |
+
}
|
213 |
+
</script>
|
214 |
+
</body>
|
215 |
+
</html>
|
216 |
+
|
217 |
+
|
218 |
+
|
219 |
+
|
220 |
+
|
221 |
+
|
222 |
+
|
booknap project/styles.css
ADDED
@@ -0,0 +1,973 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* Reset and Base Styles */
|
2 |
+
* {
|
3 |
+
margin: 0;
|
4 |
+
padding: 0;
|
5 |
+
box-sizing: border-box;
|
6 |
+
}
|
7 |
+
|
8 |
+
body {
|
9 |
+
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
10 |
+
line-height: 1.6;
|
11 |
+
color: #333;
|
12 |
+
background: linear-gradient(180deg, #3b82f6, #6366f1);
|
13 |
+
min-height: 100vh;
|
14 |
+
}
|
15 |
+
|
16 |
+
.container {
|
17 |
+
max-width: 1200px;
|
18 |
+
margin: 0 auto;
|
19 |
+
padding: 0 20px;
|
20 |
+
}
|
21 |
+
|
22 |
+
/* Header and Navigation */
|
23 |
+
.header {
|
24 |
+
background: linear-gradient(90deg, #3b82f6, #6366f1);
|
25 |
+
box-shadow: 0 2px 20px rgba(59, 130, 246, 0.3);
|
26 |
+
position: sticky;
|
27 |
+
top: 0;
|
28 |
+
z-index: 1000;
|
29 |
+
}
|
30 |
+
|
31 |
+
.nav {
|
32 |
+
padding: 1rem 0;
|
33 |
+
}
|
34 |
+
|
35 |
+
.nav-container {
|
36 |
+
display: flex;
|
37 |
+
justify-content: space-between;
|
38 |
+
align-items: center;
|
39 |
+
max-width: 1200px;
|
40 |
+
margin: 0 auto;
|
41 |
+
padding: 0 20px;
|
42 |
+
}
|
43 |
+
|
44 |
+
.nav-logo {
|
45 |
+
display: flex;
|
46 |
+
align-items: center;
|
47 |
+
gap: 0.5rem;
|
48 |
+
color: white;
|
49 |
+
font-size: 1.5rem;
|
50 |
+
font-weight: 700;
|
51 |
+
text-decoration: none;
|
52 |
+
}
|
53 |
+
|
54 |
+
.nav-logo i {
|
55 |
+
font-size: 1.8rem;
|
56 |
+
color: #ffffff;
|
57 |
+
}
|
58 |
+
|
59 |
+
.nav-menu {
|
60 |
+
display: flex;
|
61 |
+
list-style: none;
|
62 |
+
gap: 2rem;
|
63 |
+
}
|
64 |
+
|
65 |
+
.nav-link {
|
66 |
+
color: white;
|
67 |
+
text-decoration: none;
|
68 |
+
font-weight: 500;
|
69 |
+
transition: all 0.3s ease;
|
70 |
+
position: relative;
|
71 |
+
}
|
72 |
+
|
73 |
+
.nav-link:hover {
|
74 |
+
color: #ffffff;
|
75 |
+
transform: translateY(-2px);
|
76 |
+
}
|
77 |
+
|
78 |
+
.nav-link::after {
|
79 |
+
content: '';
|
80 |
+
position: absolute;
|
81 |
+
bottom: -5px;
|
82 |
+
left: 0;
|
83 |
+
width: 0;
|
84 |
+
height: 2px;
|
85 |
+
background: #ffffff;
|
86 |
+
transition: width 0.3s ease;
|
87 |
+
}
|
88 |
+
|
89 |
+
.nav-link:hover::after {
|
90 |
+
width: 100%;
|
91 |
+
}
|
92 |
+
|
93 |
+
.nav-toggle {
|
94 |
+
display: none;
|
95 |
+
flex-direction: column;
|
96 |
+
cursor: pointer;
|
97 |
+
}
|
98 |
+
|
99 |
+
.nav-toggle span {
|
100 |
+
width: 25px;
|
101 |
+
height: 3px;
|
102 |
+
background: white;
|
103 |
+
margin: 3px 0;
|
104 |
+
transition: 0.3s;
|
105 |
+
}
|
106 |
+
|
107 |
+
/* Book Details Section */
|
108 |
+
.book-details {
|
109 |
+
padding: 4rem 0;
|
110 |
+
background: linear-gradient(135deg, #3b82f6, #6366f1);
|
111 |
+
color: white;
|
112 |
+
}
|
113 |
+
|
114 |
+
.book-header {
|
115 |
+
display: grid;
|
116 |
+
grid-template-columns: 300px 1fr;
|
117 |
+
gap: 3rem;
|
118 |
+
align-items: start;
|
119 |
+
}
|
120 |
+
|
121 |
+
.book-cover-large {
|
122 |
+
position: relative;
|
123 |
+
border-radius: 15px;
|
124 |
+
overflow: hidden;
|
125 |
+
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
|
126 |
+
transition: transform 0.3s ease;
|
127 |
+
}
|
128 |
+
|
129 |
+
.book-cover-large:hover {
|
130 |
+
transform: translateY(-10px);
|
131 |
+
}
|
132 |
+
|
133 |
+
.book-cover-large img {
|
134 |
+
width: 100%;
|
135 |
+
height: auto;
|
136 |
+
display: block;
|
137 |
+
}
|
138 |
+
|
139 |
+
.book-info-large h1 {
|
140 |
+
font-size: 3rem;
|
141 |
+
font-weight: 700;
|
142 |
+
color: white;
|
143 |
+
margin-bottom: 0.5rem;
|
144 |
+
line-height: 1.2;
|
145 |
+
}
|
146 |
+
|
147 |
+
.book-author {
|
148 |
+
font-size: 1.25rem;
|
149 |
+
color: rgba(255, 255, 255, 0.9);
|
150 |
+
margin-bottom: 0.5rem;
|
151 |
+
font-weight: 500;
|
152 |
+
}
|
153 |
+
|
154 |
+
.book-category {
|
155 |
+
display: inline-block;
|
156 |
+
background: rgba(255, 255, 255, 0.2);
|
157 |
+
color: white;
|
158 |
+
padding: 0.5rem 1rem;
|
159 |
+
border-radius: 25px;
|
160 |
+
font-size: 0.875rem;
|
161 |
+
font-weight: 600;
|
162 |
+
margin-bottom: 2rem;
|
163 |
+
}
|
164 |
+
|
165 |
+
.book-actions {
|
166 |
+
display: flex;
|
167 |
+
gap: 1rem;
|
168 |
+
flex-wrap: wrap;
|
169 |
+
}
|
170 |
+
|
171 |
+
/* Buttons */
|
172 |
+
.btn {
|
173 |
+
display: inline-flex;
|
174 |
+
align-items: center;
|
175 |
+
gap: 0.5rem;
|
176 |
+
padding: 0.875rem 1.5rem;
|
177 |
+
border: none;
|
178 |
+
border-radius: 10px;
|
179 |
+
font-size: 1rem;
|
180 |
+
font-weight: 600;
|
181 |
+
text-decoration: none;
|
182 |
+
cursor: pointer;
|
183 |
+
transition: all 0.3s ease;
|
184 |
+
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
|
185 |
+
}
|
186 |
+
|
187 |
+
.btn-primary {
|
188 |
+
background: linear-gradient(90deg, #3b82f6, #6366f1);
|
189 |
+
color: white;
|
190 |
+
}
|
191 |
+
|
192 |
+
.btn-primary:hover {
|
193 |
+
transform: translateY(-2px);
|
194 |
+
box-shadow: 0 8px 25px rgba(59, 130, 246, 0.4);
|
195 |
+
}
|
196 |
+
|
197 |
+
.btn-secondary {
|
198 |
+
background: rgba(255, 255, 255, 0.2);
|
199 |
+
color: white;
|
200 |
+
border: 2px solid rgba(255, 255, 255, 0.3);
|
201 |
+
}
|
202 |
+
|
203 |
+
.btn-secondary:hover {
|
204 |
+
background: rgba(255, 255, 255, 0.3);
|
205 |
+
color: white;
|
206 |
+
transform: translateY(-2px);
|
207 |
+
}
|
208 |
+
|
209 |
+
/* Summary Section */
|
210 |
+
.summary-section {
|
211 |
+
padding: 4rem 0;
|
212 |
+
background: linear-gradient(135deg, #3b82f6, #6366f1);
|
213 |
+
color: white;
|
214 |
+
}
|
215 |
+
|
216 |
+
.summary-section h2 {
|
217 |
+
font-size: 2.5rem;
|
218 |
+
font-weight: 700;
|
219 |
+
color: white;
|
220 |
+
margin-bottom: 2rem;
|
221 |
+
text-align: center;
|
222 |
+
}
|
223 |
+
|
224 |
+
.summary-content {
|
225 |
+
max-width: 800px;
|
226 |
+
margin: 0 auto;
|
227 |
+
font-size: 1.1rem;
|
228 |
+
line-height: 1.8;
|
229 |
+
}
|
230 |
+
|
231 |
+
.summary-content h3 {
|
232 |
+
font-size: 1.5rem;
|
233 |
+
font-weight: 600;
|
234 |
+
color: white;
|
235 |
+
margin: 2rem 0 1rem 0;
|
236 |
+
}
|
237 |
+
|
238 |
+
.summary-content p {
|
239 |
+
margin-bottom: 1.5rem;
|
240 |
+
color: rgba(255, 255, 255, 0.9);
|
241 |
+
}
|
242 |
+
|
243 |
+
.summary-content ul, .summary-content ol {
|
244 |
+
margin: 1.5rem 0;
|
245 |
+
padding-left: 2rem;
|
246 |
+
}
|
247 |
+
|
248 |
+
.summary-content li {
|
249 |
+
margin-bottom: 0.75rem;
|
250 |
+
color: rgba(255, 255, 255, 0.9);
|
251 |
+
}
|
252 |
+
|
253 |
+
.summary-content strong {
|
254 |
+
color: white;
|
255 |
+
font-weight: 600;
|
256 |
+
}
|
257 |
+
|
258 |
+
/* Audio Section */
|
259 |
+
.audio-section {
|
260 |
+
padding: 4rem 0;
|
261 |
+
background: linear-gradient(135deg, #6366f1, #3b82f6);
|
262 |
+
color: white;
|
263 |
+
}
|
264 |
+
|
265 |
+
.audio-section h2 {
|
266 |
+
font-size: 2.5rem;
|
267 |
+
font-weight: 700;
|
268 |
+
margin-bottom: 2rem;
|
269 |
+
text-align: center;
|
270 |
+
}
|
271 |
+
|
272 |
+
.audio-player {
|
273 |
+
max-width: 600px;
|
274 |
+
margin: 0 auto;
|
275 |
+
background: rgba(255, 255, 255, 0.1);
|
276 |
+
backdrop-filter: blur(10px);
|
277 |
+
border-radius: 20px;
|
278 |
+
padding: 2rem;
|
279 |
+
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
|
280 |
+
}
|
281 |
+
|
282 |
+
.audio-info {
|
283 |
+
text-align: center;
|
284 |
+
margin-bottom: 2rem;
|
285 |
+
}
|
286 |
+
|
287 |
+
.audio-info h3 {
|
288 |
+
font-size: 1.5rem;
|
289 |
+
font-weight: 600;
|
290 |
+
margin-bottom: 0.5rem;
|
291 |
+
}
|
292 |
+
|
293 |
+
.audio-info p {
|
294 |
+
opacity: 0.9;
|
295 |
+
}
|
296 |
+
|
297 |
+
.audio-controls {
|
298 |
+
margin-bottom: 2rem;
|
299 |
+
}
|
300 |
+
|
301 |
+
.audio-controls audio {
|
302 |
+
width: 100%;
|
303 |
+
border-radius: 10px;
|
304 |
+
background: rgba(255, 255, 255, 0.1);
|
305 |
+
}
|
306 |
+
|
307 |
+
.audio-duration {
|
308 |
+
text-align: center;
|
309 |
+
margin-top: 1rem;
|
310 |
+
opacity: 0.8;
|
311 |
+
}
|
312 |
+
|
313 |
+
.audio-features {
|
314 |
+
display: flex;
|
315 |
+
justify-content: center;
|
316 |
+
gap: 1rem;
|
317 |
+
flex-wrap: wrap;
|
318 |
+
}
|
319 |
+
|
320 |
+
.feature-btn {
|
321 |
+
background: rgba(255, 255, 255, 0.2);
|
322 |
+
border: none;
|
323 |
+
color: white;
|
324 |
+
padding: 0.75rem 1rem;
|
325 |
+
border-radius: 8px;
|
326 |
+
cursor: pointer;
|
327 |
+
transition: all 0.3s ease;
|
328 |
+
font-weight: 500;
|
329 |
+
}
|
330 |
+
|
331 |
+
.feature-btn:hover {
|
332 |
+
background: rgba(255, 255, 255, 0.3);
|
333 |
+
transform: translateY(-2px);
|
334 |
+
}
|
335 |
+
|
336 |
+
/* Related Books Section */
|
337 |
+
.related-books {
|
338 |
+
padding: 4rem 0;
|
339 |
+
background: linear-gradient(135deg, #3b82f6, #6366f1);
|
340 |
+
color: white;
|
341 |
+
}
|
342 |
+
|
343 |
+
.related-books h2 {
|
344 |
+
font-size: 2.5rem;
|
345 |
+
font-weight: 700;
|
346 |
+
color: white;
|
347 |
+
margin-bottom: 2rem;
|
348 |
+
text-align: center;
|
349 |
+
}
|
350 |
+
|
351 |
+
.books-grid {
|
352 |
+
display: grid;
|
353 |
+
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
354 |
+
gap: 2rem;
|
355 |
+
margin-top: 2rem;
|
356 |
+
}
|
357 |
+
|
358 |
+
.book-card {
|
359 |
+
background: rgba(255, 255, 255, 0.1);
|
360 |
+
border-radius: 15px;
|
361 |
+
overflow: hidden;
|
362 |
+
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
|
363 |
+
transition: all 0.3s ease;
|
364 |
+
cursor: pointer;
|
365 |
+
backdrop-filter: blur(10px);
|
366 |
+
}
|
367 |
+
|
368 |
+
.book-card:hover {
|
369 |
+
transform: translateY(-10px);
|
370 |
+
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
|
371 |
+
background: rgba(255, 255, 255, 0.15);
|
372 |
+
}
|
373 |
+
|
374 |
+
.book-cover {
|
375 |
+
position: relative;
|
376 |
+
height: 200px;
|
377 |
+
overflow: hidden;
|
378 |
+
}
|
379 |
+
|
380 |
+
.book-cover img {
|
381 |
+
width: 100%;
|
382 |
+
height: 100%;
|
383 |
+
object-fit: cover;
|
384 |
+
transition: transform 0.3s ease;
|
385 |
+
}
|
386 |
+
|
387 |
+
.book-card:hover .book-cover img {
|
388 |
+
transform: scale(1.05);
|
389 |
+
}
|
390 |
+
|
391 |
+
.book-overlay {
|
392 |
+
position: absolute;
|
393 |
+
top: 0;
|
394 |
+
left: 0;
|
395 |
+
right: 0;
|
396 |
+
bottom: 0;
|
397 |
+
background: rgba(59, 130, 246, 0.8);
|
398 |
+
display: flex;
|
399 |
+
align-items: center;
|
400 |
+
justify-content: center;
|
401 |
+
opacity: 0;
|
402 |
+
transition: opacity 0.3s ease;
|
403 |
+
}
|
404 |
+
|
405 |
+
.book-overlay i {
|
406 |
+
color: white;
|
407 |
+
font-size: 2rem;
|
408 |
+
}
|
409 |
+
|
410 |
+
.book-card:hover .book-overlay {
|
411 |
+
opacity: 1;
|
412 |
+
}
|
413 |
+
|
414 |
+
.book-info {
|
415 |
+
padding: 1.5rem;
|
416 |
+
}
|
417 |
+
|
418 |
+
.book-info h3 {
|
419 |
+
font-size: 1.25rem;
|
420 |
+
font-weight: 600;
|
421 |
+
color: white;
|
422 |
+
margin-bottom: 0.5rem;
|
423 |
+
line-height: 1.3;
|
424 |
+
}
|
425 |
+
|
426 |
+
.book-info .book-author {
|
427 |
+
color: rgba(255, 255, 255, 0.8);
|
428 |
+
font-size: 0.875rem;
|
429 |
+
margin-bottom: 0.25rem;
|
430 |
+
}
|
431 |
+
|
432 |
+
.book-info .book-category {
|
433 |
+
background: rgba(255, 255, 255, 0.2);
|
434 |
+
color: white;
|
435 |
+
padding: 0.25rem 0.75rem;
|
436 |
+
border-radius: 15px;
|
437 |
+
font-size: 0.75rem;
|
438 |
+
font-weight: 600;
|
439 |
+
display: inline-block;
|
440 |
+
}
|
441 |
+
|
442 |
+
/* Footer */
|
443 |
+
.footer {
|
444 |
+
background: linear-gradient(90deg, #3b82f6, #6366f1);
|
445 |
+
color: white;
|
446 |
+
text-align: center;
|
447 |
+
padding: 2rem 0;
|
448 |
+
}
|
449 |
+
|
450 |
+
.footer p {
|
451 |
+
opacity: 0.8;
|
452 |
+
}
|
453 |
+
|
454 |
+
/* Animated Tabs Section - Blinkist Style */
|
455 |
+
.animated-tabs-section {
|
456 |
+
padding: 6rem 0;
|
457 |
+
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
|
458 |
+
overflow: hidden;
|
459 |
+
}
|
460 |
+
|
461 |
+
.tabs-container {
|
462 |
+
max-width: 1200px;
|
463 |
+
margin: 0 auto;
|
464 |
+
padding: 0 20px;
|
465 |
+
}
|
466 |
+
|
467 |
+
.tabs-header {
|
468 |
+
text-align: center;
|
469 |
+
margin-bottom: 4rem;
|
470 |
+
}
|
471 |
+
|
472 |
+
.tabs-header h2 {
|
473 |
+
font-size: 3rem;
|
474 |
+
font-weight: 700;
|
475 |
+
color: #2d3748;
|
476 |
+
margin-bottom: 1rem;
|
477 |
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
478 |
+
-webkit-background-clip: text;
|
479 |
+
-webkit-text-fill-color: transparent;
|
480 |
+
background-clip: text;
|
481 |
+
}
|
482 |
+
|
483 |
+
.tabs-header p {
|
484 |
+
font-size: 1.2rem;
|
485 |
+
color: #4a5568;
|
486 |
+
max-width: 600px;
|
487 |
+
margin: 0 auto;
|
488 |
+
}
|
489 |
+
|
490 |
+
.tabs-wrapper {
|
491 |
+
display: flex;
|
492 |
+
flex-direction: column;
|
493 |
+
align-items: center;
|
494 |
+
gap: 3rem;
|
495 |
+
}
|
496 |
+
|
497 |
+
.tabs-nav {
|
498 |
+
display: flex;
|
499 |
+
background: white;
|
500 |
+
border-radius: 50px;
|
501 |
+
padding: 0.5rem;
|
502 |
+
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
|
503 |
+
position: relative;
|
504 |
+
overflow: hidden;
|
505 |
+
}
|
506 |
+
|
507 |
+
.tab-button {
|
508 |
+
background: none;
|
509 |
+
border: none;
|
510 |
+
padding: 1rem 2rem;
|
511 |
+
border-radius: 40px;
|
512 |
+
font-size: 1rem;
|
513 |
+
font-weight: 600;
|
514 |
+
color: #4a5568;
|
515 |
+
cursor: pointer;
|
516 |
+
transition: all 0.3s ease;
|
517 |
+
position: relative;
|
518 |
+
z-index: 2;
|
519 |
+
white-space: nowrap;
|
520 |
+
display: flex;
|
521 |
+
align-items: center;
|
522 |
+
gap: 0.5rem;
|
523 |
+
}
|
524 |
+
|
525 |
+
.tab-button.active {
|
526 |
+
color: white;
|
527 |
+
}
|
528 |
+
|
529 |
+
.tab-button i {
|
530 |
+
font-size: 1.2rem;
|
531 |
+
}
|
532 |
+
|
533 |
+
.tab-slider {
|
534 |
+
position: absolute;
|
535 |
+
top: 0.5rem;
|
536 |
+
left: 0.5rem;
|
537 |
+
height: calc(100% - 1rem);
|
538 |
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
539 |
+
border-radius: 40px;
|
540 |
+
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
541 |
+
z-index: 1;
|
542 |
+
}
|
543 |
+
|
544 |
+
.tabs-content {
|
545 |
+
width: 100%;
|
546 |
+
max-width: 1000px;
|
547 |
+
position: relative;
|
548 |
+
}
|
549 |
+
|
550 |
+
.tab-panel {
|
551 |
+
display: none;
|
552 |
+
animation: fadeInUp 0.6s ease-out;
|
553 |
+
}
|
554 |
+
|
555 |
+
.tab-panel.active {
|
556 |
+
display: block;
|
557 |
+
}
|
558 |
+
|
559 |
+
.tab-panel-content {
|
560 |
+
background: white;
|
561 |
+
border-radius: 20px;
|
562 |
+
padding: 3rem;
|
563 |
+
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
|
564 |
+
position: relative;
|
565 |
+
overflow: hidden;
|
566 |
+
}
|
567 |
+
|
568 |
+
.tab-panel-content::before {
|
569 |
+
content: '';
|
570 |
+
position: absolute;
|
571 |
+
top: 0;
|
572 |
+
left: 0;
|
573 |
+
right: 0;
|
574 |
+
height: 4px;
|
575 |
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
576 |
+
}
|
577 |
+
|
578 |
+
/* Tab-specific styles */
|
579 |
+
.read-tab {
|
580 |
+
display: grid;
|
581 |
+
grid-template-columns: 1fr 1fr;
|
582 |
+
gap: 3rem;
|
583 |
+
align-items: center;
|
584 |
+
}
|
585 |
+
|
586 |
+
.read-content h3 {
|
587 |
+
font-size: 2rem;
|
588 |
+
font-weight: 700;
|
589 |
+
color: #2d3748;
|
590 |
+
margin-bottom: 1rem;
|
591 |
+
}
|
592 |
+
|
593 |
+
.read-content p {
|
594 |
+
font-size: 1.1rem;
|
595 |
+
color: #4a5568;
|
596 |
+
line-height: 1.7;
|
597 |
+
margin-bottom: 2rem;
|
598 |
+
}
|
599 |
+
|
600 |
+
.read-features {
|
601 |
+
display: flex;
|
602 |
+
flex-direction: column;
|
603 |
+
gap: 1rem;
|
604 |
+
}
|
605 |
+
|
606 |
+
.read-feature {
|
607 |
+
display: flex;
|
608 |
+
align-items: center;
|
609 |
+
gap: 1rem;
|
610 |
+
padding: 1rem;
|
611 |
+
background: #f8fafc;
|
612 |
+
border-radius: 10px;
|
613 |
+
transition: all 0.3s ease;
|
614 |
+
}
|
615 |
+
|
616 |
+
.read-feature:hover {
|
617 |
+
background: #e2e8f0;
|
618 |
+
transform: translateX(10px);
|
619 |
+
}
|
620 |
+
|
621 |
+
.read-feature i {
|
622 |
+
font-size: 1.5rem;
|
623 |
+
color: #667eea;
|
624 |
+
width: 40px;
|
625 |
+
height: 40px;
|
626 |
+
display: flex;
|
627 |
+
align-items: center;
|
628 |
+
justify-content: center;
|
629 |
+
background: white;
|
630 |
+
border-radius: 50%;
|
631 |
+
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.2);
|
632 |
+
}
|
633 |
+
|
634 |
+
.read-feature-text h4 {
|
635 |
+
font-weight: 600;
|
636 |
+
color: #2d3748;
|
637 |
+
margin-bottom: 0.25rem;
|
638 |
+
}
|
639 |
+
|
640 |
+
.read-feature-text p {
|
641 |
+
font-size: 0.9rem;
|
642 |
+
color: #4a5568;
|
643 |
+
margin: 0;
|
644 |
+
}
|
645 |
+
|
646 |
+
.read-visual {
|
647 |
+
position: relative;
|
648 |
+
text-align: center;
|
649 |
+
}
|
650 |
+
|
651 |
+
.read-visual img {
|
652 |
+
max-width: 100%;
|
653 |
+
height: auto;
|
654 |
+
border-radius: 15px;
|
655 |
+
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
|
656 |
+
}
|
657 |
+
|
658 |
+
.listen-tab {
|
659 |
+
display: grid;
|
660 |
+
grid-template-columns: 1fr 1fr;
|
661 |
+
gap: 3rem;
|
662 |
+
align-items: center;
|
663 |
+
}
|
664 |
+
|
665 |
+
.listen-content h3 {
|
666 |
+
font-size: 2rem;
|
667 |
+
font-weight: 700;
|
668 |
+
color: #2d3748;
|
669 |
+
margin-bottom: 1rem;
|
670 |
+
}
|
671 |
+
|
672 |
+
.listen-content p {
|
673 |
+
font-size: 1.1rem;
|
674 |
+
color: #4a5568;
|
675 |
+
line-height: 1.7;
|
676 |
+
margin-bottom: 2rem;
|
677 |
+
}
|
678 |
+
|
679 |
+
.listen-features {
|
680 |
+
display: flex;
|
681 |
+
flex-direction: column;
|
682 |
+
gap: 1rem;
|
683 |
+
}
|
684 |
+
|
685 |
+
.listen-feature {
|
686 |
+
display: flex;
|
687 |
+
align-items: center;
|
688 |
+
gap: 1rem;
|
689 |
+
padding: 1rem;
|
690 |
+
background: #f8fafc;
|
691 |
+
border-radius: 10px;
|
692 |
+
transition: all 0.3s ease;
|
693 |
+
}
|
694 |
+
|
695 |
+
.listen-feature:hover {
|
696 |
+
background: #e2e8f0;
|
697 |
+
transform: translateX(10px);
|
698 |
+
}
|
699 |
+
|
700 |
+
.listen-feature i {
|
701 |
+
font-size: 1.5rem;
|
702 |
+
color: #667eea;
|
703 |
+
width: 40px;
|
704 |
+
height: 40px;
|
705 |
+
display: flex;
|
706 |
+
align-items: center;
|
707 |
+
justify-content: center;
|
708 |
+
background: white;
|
709 |
+
border-radius: 50%;
|
710 |
+
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.2);
|
711 |
+
}
|
712 |
+
|
713 |
+
.listen-feature-text h4 {
|
714 |
+
font-weight: 600;
|
715 |
+
color: #2d3748;
|
716 |
+
margin-bottom: 0.25rem;
|
717 |
+
}
|
718 |
+
|
719 |
+
.listen-feature-text p {
|
720 |
+
font-size: 0.9rem;
|
721 |
+
color: #4a5568;
|
722 |
+
margin: 0;
|
723 |
+
}
|
724 |
+
|
725 |
+
.listen-visual {
|
726 |
+
position: relative;
|
727 |
+
text-align: center;
|
728 |
+
}
|
729 |
+
|
730 |
+
.listen-visual img {
|
731 |
+
max-width: 100%;
|
732 |
+
height: auto;
|
733 |
+
border-radius: 15px;
|
734 |
+
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
|
735 |
+
}
|
736 |
+
|
737 |
+
.learn-tab {
|
738 |
+
text-align: center;
|
739 |
+
}
|
740 |
+
|
741 |
+
.learn-content h3 {
|
742 |
+
font-size: 2.5rem;
|
743 |
+
font-weight: 700;
|
744 |
+
color: #2d3748;
|
745 |
+
margin-bottom: 1.5rem;
|
746 |
+
}
|
747 |
+
|
748 |
+
.learn-content p {
|
749 |
+
font-size: 1.2rem;
|
750 |
+
color: #4a5568;
|
751 |
+
line-height: 1.7;
|
752 |
+
margin-bottom: 3rem;
|
753 |
+
max-width: 600px;
|
754 |
+
margin-left: auto;
|
755 |
+
margin-right: auto;
|
756 |
+
}
|
757 |
+
|
758 |
+
.learn-grid {
|
759 |
+
display: grid;
|
760 |
+
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
761 |
+
gap: 2rem;
|
762 |
+
margin-top: 3rem;
|
763 |
+
}
|
764 |
+
|
765 |
+
.learn-card {
|
766 |
+
background: #f8fafc;
|
767 |
+
border-radius: 15px;
|
768 |
+
padding: 2rem;
|
769 |
+
transition: all 0.3s ease;
|
770 |
+
border: 2px solid transparent;
|
771 |
+
}
|
772 |
+
|
773 |
+
.learn-card:hover {
|
774 |
+
background: white;
|
775 |
+
border-color: #667eea;
|
776 |
+
transform: translateY(-10px);
|
777 |
+
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
|
778 |
+
}
|
779 |
+
|
780 |
+
.learn-card i {
|
781 |
+
font-size: 3rem;
|
782 |
+
color: #667eea;
|
783 |
+
margin-bottom: 1rem;
|
784 |
+
}
|
785 |
+
|
786 |
+
.learn-card h4 {
|
787 |
+
font-size: 1.25rem;
|
788 |
+
font-weight: 600;
|
789 |
+
color: #2d3748;
|
790 |
+
margin-bottom: 1rem;
|
791 |
+
}
|
792 |
+
|
793 |
+
.learn-card p {
|
794 |
+
font-size: 1rem;
|
795 |
+
color: #4a5568;
|
796 |
+
line-height: 1.6;
|
797 |
+
margin: 0;
|
798 |
+
}
|
799 |
+
|
800 |
+
/* Animations */
|
801 |
+
@keyframes fadeInUp {
|
802 |
+
from {
|
803 |
+
opacity: 0;
|
804 |
+
transform: translateY(30px);
|
805 |
+
}
|
806 |
+
to {
|
807 |
+
opacity: 1;
|
808 |
+
transform: translateY(0);
|
809 |
+
}
|
810 |
+
}
|
811 |
+
|
812 |
+
@keyframes slideIn {
|
813 |
+
from {
|
814 |
+
opacity: 0;
|
815 |
+
transform: translateX(-30px);
|
816 |
+
}
|
817 |
+
to {
|
818 |
+
opacity: 1;
|
819 |
+
transform: translateX(0);
|
820 |
+
}
|
821 |
+
}
|
822 |
+
|
823 |
+
/* Responsive Design */
|
824 |
+
@media (max-width: 768px) {
|
825 |
+
.nav-menu {
|
826 |
+
display: none;
|
827 |
+
}
|
828 |
+
|
829 |
+
.nav-toggle {
|
830 |
+
display: flex;
|
831 |
+
}
|
832 |
+
|
833 |
+
.book-header {
|
834 |
+
grid-template-columns: 1fr;
|
835 |
+
gap: 2rem;
|
836 |
+
text-align: center;
|
837 |
+
}
|
838 |
+
|
839 |
+
.book-cover-large {
|
840 |
+
max-width: 250px;
|
841 |
+
margin: 0 auto;
|
842 |
+
}
|
843 |
+
|
844 |
+
.book-info-large h1 {
|
845 |
+
font-size: 2rem;
|
846 |
+
}
|
847 |
+
|
848 |
+
.book-actions {
|
849 |
+
justify-content: center;
|
850 |
+
}
|
851 |
+
|
852 |
+
.summary-content {
|
853 |
+
font-size: 1rem;
|
854 |
+
}
|
855 |
+
|
856 |
+
.audio-player {
|
857 |
+
margin: 0 1rem;
|
858 |
+
}
|
859 |
+
|
860 |
+
.books-grid {
|
861 |
+
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
862 |
+
gap: 1.5rem;
|
863 |
+
}
|
864 |
+
|
865 |
+
/* Animated Tabs Responsive */
|
866 |
+
.tabs-header h2 {
|
867 |
+
font-size: 2rem;
|
868 |
+
}
|
869 |
+
|
870 |
+
.tabs-nav {
|
871 |
+
flex-direction: column;
|
872 |
+
border-radius: 20px;
|
873 |
+
padding: 0.25rem;
|
874 |
+
}
|
875 |
+
|
876 |
+
.tab-button {
|
877 |
+
padding: 0.75rem 1.5rem;
|
878 |
+
font-size: 0.9rem;
|
879 |
+
}
|
880 |
+
|
881 |
+
.tab-slider {
|
882 |
+
display: none;
|
883 |
+
}
|
884 |
+
|
885 |
+
.tab-button.active {
|
886 |
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
887 |
+
color: white;
|
888 |
+
}
|
889 |
+
|
890 |
+
.read-tab,
|
891 |
+
.listen-tab {
|
892 |
+
grid-template-columns: 1fr;
|
893 |
+
gap: 2rem;
|
894 |
+
}
|
895 |
+
|
896 |
+
.tab-panel-content {
|
897 |
+
padding: 2rem;
|
898 |
+
}
|
899 |
+
|
900 |
+
.learn-grid {
|
901 |
+
grid-template-columns: 1fr;
|
902 |
+
}
|
903 |
+
}
|
904 |
+
|
905 |
+
@media (max-width: 480px) {
|
906 |
+
.container {
|
907 |
+
padding: 0 15px;
|
908 |
+
}
|
909 |
+
|
910 |
+
.book-info-large h1 {
|
911 |
+
font-size: 1.75rem;
|
912 |
+
}
|
913 |
+
|
914 |
+
.btn {
|
915 |
+
padding: 0.75rem 1rem;
|
916 |
+
font-size: 0.875rem;
|
917 |
+
}
|
918 |
+
|
919 |
+
.summary-section h2,
|
920 |
+
.audio-section h2,
|
921 |
+
.related-books h2 {
|
922 |
+
font-size: 2rem;
|
923 |
+
}
|
924 |
+
|
925 |
+
.books-grid {
|
926 |
+
grid-template-columns: 1fr;
|
927 |
+
}
|
928 |
+
|
929 |
+
/* Animated Tabs Mobile */
|
930 |
+
.tabs-header h2 {
|
931 |
+
font-size: 1.75rem;
|
932 |
+
}
|
933 |
+
|
934 |
+
.tabs-header p {
|
935 |
+
font-size: 1rem;
|
936 |
+
}
|
937 |
+
|
938 |
+
.tab-panel-content {
|
939 |
+
padding: 1.5rem;
|
940 |
+
}
|
941 |
+
|
942 |
+
.read-content h3,
|
943 |
+
.listen-content h3 {
|
944 |
+
font-size: 1.5rem;
|
945 |
+
}
|
946 |
+
|
947 |
+
.learn-content h3 {
|
948 |
+
font-size: 2rem;
|
949 |
+
}
|
950 |
+
}
|
951 |
+
|
952 |
+
/* Smooth scrolling */
|
953 |
+
html {
|
954 |
+
scroll-behavior: smooth;
|
955 |
+
}
|
956 |
+
|
957 |
+
/* Custom scrollbar */
|
958 |
+
::-webkit-scrollbar {
|
959 |
+
width: 8px;
|
960 |
+
}
|
961 |
+
|
962 |
+
::-webkit-scrollbar-track {
|
963 |
+
background: #f1f1f1;
|
964 |
+
}
|
965 |
+
|
966 |
+
::-webkit-scrollbar-thumb {
|
967 |
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
968 |
+
border-radius: 4px;
|
969 |
+
}
|
970 |
+
|
971 |
+
::-webkit-scrollbar-thumb:hover {
|
972 |
+
background: linear-gradient(135deg, #5a67d8 0%, #6b46c1 100%);
|
973 |
+
}
|
booknap project/test_connection.py
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/env python3
|
2 |
+
"""
|
3 |
+
Simple database connection test
|
4 |
+
"""
|
5 |
+
|
6 |
+
import os
|
7 |
+
from sqlalchemy import create_engine, text
|
8 |
+
|
9 |
+
def test_connection():
|
10 |
+
"""Test database connection"""
|
11 |
+
|
12 |
+
# You need to replace YOUR_ACTUAL_PASSWORD with your real Supabase password
|
13 |
+
DATABASE_URL = "postgresql://postgres:YOUR_ACTUAL_PASSWORD@db.ckrqyjfdifjbsuuofegd.supabase.co:5432/postgres"
|
14 |
+
|
15 |
+
print("Testing database connection...")
|
16 |
+
print(f"Host: db.ckrqyjfdifjbsuuofegd.supabase.co")
|
17 |
+
print(f"Port: 5432")
|
18 |
+
print(f"Database: postgres")
|
19 |
+
print(f"User: postgres")
|
20 |
+
print()
|
21 |
+
|
22 |
+
try:
|
23 |
+
# Create engine
|
24 |
+
engine = create_engine(DATABASE_URL, pool_pre_ping=True)
|
25 |
+
|
26 |
+
# Test connection
|
27 |
+
with engine.connect() as conn:
|
28 |
+
print("β
Connection successful!")
|
29 |
+
|
30 |
+
# Test a simple query
|
31 |
+
result = conn.execute(text("SELECT version()"))
|
32 |
+
version = result.fetchone()[0]
|
33 |
+
print(f"β
Database version: {version}")
|
34 |
+
|
35 |
+
# Test if we can create a table
|
36 |
+
print("β
Database is accessible and ready for use!")
|
37 |
+
|
38 |
+
except Exception as e:
|
39 |
+
print(f"β Connection failed: {e}")
|
40 |
+
print()
|
41 |
+
print("To fix this:")
|
42 |
+
print("1. Update the password in this script (replace YOUR_ACTUAL_PASSWORD)")
|
43 |
+
print("2. Or set the environment variable:")
|
44 |
+
print(" export DATABASE_URL='postgresql://postgres:YOUR_PASSWORD@db.ckrqyjfdifjbsuuofegd.supabase.co:5432/postgres'")
|
45 |
+
print("3. Make sure your IP is whitelisted in Supabase")
|
46 |
+
|
47 |
+
if __name__ == "__main__":
|
48 |
+
test_connection()
|
49 |
+
|