mobile bluesky app made with flutter
lazurite.stormlightlabs.org/
mobile
bluesky
flutter
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, maximum-scale=1.0, user-scalable=no" />
6 <title>Home - Lazurite</title>
7 <link rel="preconnect" href="https://fonts.googleapis.com" />
8 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
9 <link href="https://fonts.googleapis.com/css2?family=Lora:wght@400;500;600;700&display=swap" rel="stylesheet" />
10 <link
11 href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,100..1000;1,9..40,100..1000&display=swap"
12 rel="stylesheet" />
13 <link rel="stylesheet" href="styles.css" />
14 <style>
15 .feed-container {
16 padding-bottom: 88px;
17 }
18
19 .compose-box {
20 padding: 16px;
21 border-bottom: 1px solid var(--border);
22 background-color: var(--bg);
23 }
24
25 .compose-inner {
26 display: flex;
27 gap: 12px;
28 }
29
30 .compose-input-wrapper {
31 flex: 1;
32 }
33
34 .compose-input {
35 width: 100%;
36 border: none;
37 background: transparent;
38 color: var(--text-primary);
39 font-size: 16px;
40 resize: none;
41 outline: none;
42 font-family: inherit;
43 min-height: 24px;
44 }
45
46 .compose-input::placeholder {
47 color: var(--text-muted);
48 }
49
50 .compose-actions {
51 display: flex;
52 justify-content: space-between;
53 align-items: center;
54 margin-top: 12px;
55 padding-left: 60px;
56 }
57
58 .compose-tools {
59 display: flex;
60 gap: 8px;
61 }
62
63 .compose-tool {
64 width: 36px;
65 height: 36px;
66 border-radius: 50%;
67 border: none;
68 background: transparent;
69 color: var(--accent-primary);
70 cursor: pointer;
71 display: flex;
72 align-items: center;
73 justify-content: center;
74 transition: background-color 0.2s ease;
75 }
76
77 .compose-tool:hover {
78 background-color: rgba(0, 102, 255, 0.1);
79 }
80
81 .compose-tool svg {
82 width: 20px;
83 height: 20px;
84 }
85
86 .compose-submit {
87 padding: 8px 20px;
88 border-radius: 9999px;
89 border: none;
90 background-color: var(--accent-primary);
91 color: white;
92 font-weight: 600;
93 font-size: 14px;
94 cursor: pointer;
95 transition: background-color 0.2s ease;
96 }
97
98 .compose-submit:hover {
99 background-color: var(--accent-primary-hover);
100 }
101
102 .feed-tabs {
103 display: flex;
104 border-bottom: 1px solid var(--border);
105 background-color: var(--bg);
106 }
107
108 .feed-tab {
109 flex: 1;
110 padding: 16px;
111 text-align: center;
112 font-weight: 600;
113 font-size: 15px;
114 color: var(--text-secondary);
115 cursor: pointer;
116 border-bottom: 2px solid transparent;
117 transition: all 0.2s ease;
118 background: none;
119 border-top: none;
120 border-left: none;
121 border-right: none;
122 }
123
124 .feed-tab:hover {
125 background-color: var(--surface);
126 color: var(--text-primary);
127 }
128
129 .feed-tab.active {
130 color: var(--text-primary);
131 border-bottom-color: var(--accent-primary);
132 }
133
134 .post-facet-mention {
135 color: var(--accent-primary);
136 text-decoration: none;
137 font-weight: 500;
138 }
139
140 .post-facet-mention:hover {
141 text-decoration: underline;
142 }
143
144 .post-facet-hashtag {
145 color: var(--accent-secondary);
146 text-decoration: none;
147 font-weight: 500;
148 }
149
150 .post-facet-hashtag:hover {
151 text-decoration: underline;
152 }
153
154 .post-facet-link {
155 color: var(--accent-primary);
156 text-decoration: underline;
157 }
158
159 .post-embed {
160 margin-top: 12px;
161 border: 1px solid var(--border);
162 border-radius: 12px;
163 overflow: hidden;
164 }
165
166 .post-embed-image {
167 width: 100%;
168 height: 200px;
169 background: linear-gradient(135deg, var(--surface) 0%, var(--surface-variant) 100%);
170 display: flex;
171 align-items: center;
172 justify-content: center;
173 color: var(--text-muted);
174 }
175
176 .post-embed-content {
177 padding: 12px;
178 }
179
180 .post-embed-title {
181 font-weight: 600;
182 color: var(--text-primary);
183 font-size: 14px;
184 margin-bottom: 4px;
185 }
186
187 .post-embed-url {
188 color: var(--text-muted);
189 font-size: 12px;
190 }
191
192 .menu-overlay {
193 position: fixed;
194 top: 0;
195 left: 0;
196 right: 0;
197 bottom: 0;
198 background-color: rgba(0, 0, 0, 0.5);
199 z-index: 200;
200 opacity: 0;
201 visibility: hidden;
202 transition:
203 opacity 0.2s ease,
204 visibility 0.2s ease;
205 }
206
207 .menu-overlay.open {
208 opacity: 1;
209 visibility: visible;
210 }
211
212 .side-menu {
213 position: fixed;
214 top: 0;
215 left: 0;
216 width: 280px;
217 max-width: 80%;
218 height: 100%;
219 background-color: var(--surface);
220 z-index: 201;
221 transform: translateX(-100%);
222 transition: transform 0.3s ease;
223 overflow-y: auto;
224 }
225
226 .side-menu.open {
227 transform: translateX(0);
228 }
229
230 .menu-header {
231 padding: 16px;
232 border-bottom: 1px solid var(--border);
233 display: flex;
234 align-items: center;
235 justify-content: space-between;
236 }
237
238 .menu-close {
239 width: 36px;
240 height: 36px;
241 border-radius: 50%;
242 border: none;
243 background: transparent;
244 color: var(--text-secondary);
245 cursor: pointer;
246 display: flex;
247 align-items: center;
248 justify-content: center;
249 transition: background-color 0.2s ease;
250 }
251
252 .menu-close:hover {
253 background-color: var(--surface-variant);
254 }
255
256 .menu-close svg {
257 width: 24px;
258 height: 24px;
259 }
260
261 .menu-user {
262 padding: 16px;
263 border-bottom: 1px solid var(--border);
264 display: flex;
265 align-items: center;
266 gap: 12px;
267 }
268
269 .menu-user-avatar {
270 width: 48px;
271 height: 48px;
272 border-radius: 50%;
273 background-color: var(--surface-variant);
274 display: flex;
275 align-items: center;
276 justify-content: center;
277 font-weight: 600;
278 color: var(--text-primary);
279 }
280
281 .menu-user-info {
282 flex: 1;
283 }
284
285 .menu-user-name {
286 font-weight: 600;
287 color: var(--text-primary);
288 font-size: 15px;
289 }
290
291 .menu-user-handle {
292 color: var(--text-secondary);
293 font-size: 14px;
294 }
295
296 .menu-nav {
297 padding: 8px 0;
298 }
299
300 .menu-nav-item {
301 display: flex;
302 align-items: center;
303 gap: 12px;
304 padding: 14px 16px;
305 color: var(--text-primary);
306 text-decoration: none;
307 transition: background-color 0.2s ease;
308 }
309
310 .menu-nav-item:hover {
311 background-color: var(--surface-variant);
312 }
313
314 .menu-nav-item svg {
315 width: 22px;
316 height: 22px;
317 color: var(--text-secondary);
318 }
319
320 .menu-nav-item span {
321 font-size: 15px;
322 font-weight: 500;
323 }
324
325 .menu-divider {
326 height: 1px;
327 background-color: var(--border);
328 margin: 8px 16px;
329 }
330
331 .header-menu-btn {
332 width: 36px;
333 height: 36px;
334 border-radius: 50%;
335 border: none;
336 background: transparent;
337 color: var(--accent-primary);
338 cursor: pointer;
339 display: flex;
340 align-items: center;
341 justify-content: center;
342 transition: background-color 0.2s ease;
343 }
344
345 .header-menu-btn:hover {
346 background-color: rgba(0, 102, 255, 0.1);
347 }
348
349 .header-menu-btn svg {
350 width: 24px;
351 height: 24px;
352 }
353 </style>
354 </head>
355 <body>
356 <div class="mobile-container">
357 <!-- Menu Overlay -->
358 <div class="menu-overlay" id="menuOverlay" onclick="closeMenu()"></div>
359
360 <!-- Side Menu -->
361 <nav class="side-menu" id="sideMenu">
362 <div class="menu-header">
363 <span style="font-weight: 600; color: var(--text-primary)">Menu</span>
364 <button class="menu-close" onclick="closeMenu()">
365 <svg
366 viewBox="0 0 24 24"
367 fill="none"
368 stroke="currentColor"
369 stroke-width="2"
370 stroke-linecap="round"
371 stroke-linejoin="round">
372 <line x1="18" y1="6" x2="6" y2="18"></line>
373 <line x1="6" y1="6" x2="18" y2="18"></line>
374 </svg>
375 </button>
376 </div>
377
378 <a href="profile.html" class="menu-user">
379 <div class="menu-user-avatar">JD</div>
380 <div class="menu-user-info">
381 <div class="menu-user-name">John Doe</div>
382 <div class="menu-user-handle">@johndoe.bsky.social</div>
383 </div>
384 </a>
385
386 <div class="menu-nav">
387 <a href="home.html" class="menu-nav-item">
388 <svg
389 viewBox="0 0 24 24"
390 fill="none"
391 stroke="currentColor"
392 stroke-width="2"
393 stroke-linecap="round"
394 stroke-linejoin="round">
395 <path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
396 <polyline points="9 22 9 12 15 12 15 22"></polyline>
397 </svg>
398 <span>Home</span>
399 </a>
400
401 <a href="search.html" class="menu-nav-item">
402 <svg
403 viewBox="0 0 24 24"
404 fill="none"
405 stroke="currentColor"
406 stroke-width="2"
407 stroke-linecap="round"
408 stroke-linejoin="round">
409 <circle cx="11" cy="11" r="8"></circle>
410 <line x1="21" y1="21" x2="16.65" y2="16.65"></line>
411 </svg>
412 <span>Search</span>
413 </a>
414
415 <a href="feeds.html" class="menu-nav-item">
416 <svg
417 viewBox="0 0 24 24"
418 fill="none"
419 stroke="currentColor"
420 stroke-width="2"
421 stroke-linecap="round"
422 stroke-linejoin="round">
423 <path d="M4 11a9 9 0 0 1 9 9"></path>
424 <path d="M4 4a16 16 0 0 1 16 16"></path>
425 <circle cx="5" cy="19" r="1"></circle>
426 </svg>
427 <span>Feeds</span>
428 </a>
429
430 <a href="notifications.html" class="menu-nav-item">
431 <svg
432 viewBox="0 0 24 24"
433 fill="none"
434 stroke="currentColor"
435 stroke-width="2"
436 stroke-linecap="round"
437 stroke-linejoin="round">
438 <path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"></path>
439 <path d="M13.73 21a2 2 0 0 1-3.46 0"></path>
440 </svg>
441 <span>Notifications</span>
442 </a>
443
444 <a href="messages.html" class="menu-nav-item">
445 <svg
446 viewBox="0 0 24 24"
447 fill="none"
448 stroke="currentColor"
449 stroke-width="2"
450 stroke-linecap="round"
451 stroke-linejoin="round">
452 <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
453 </svg>
454 <span>Messages</span>
455 </a>
456
457 <a href="profile.html" class="menu-nav-item">
458 <svg
459 viewBox="0 0 24 24"
460 fill="none"
461 stroke="currentColor"
462 stroke-width="2"
463 stroke-linecap="round"
464 stroke-linejoin="round">
465 <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path>
466 <circle cx="12" cy="7" r="4"></circle>
467 </svg>
468 <span>Profile</span>
469 </a>
470
471 <div class="menu-divider"></div>
472
473 <a href="compose.html" class="menu-nav-item">
474 <svg
475 viewBox="0 0 24 24"
476 fill="none"
477 stroke="currentColor"
478 stroke-width="2"
479 stroke-linecap="round"
480 stroke-linejoin="round">
481 <line x1="12" y1="5" x2="12" y2="19"></line>
482 <line x1="5" y1="12" x2="19" y2="12"></line>
483 </svg>
484 <span>New Post</span>
485 </a>
486
487 <a href="settings.html" class="menu-nav-item">
488 <svg
489 viewBox="0 0 24 24"
490 fill="none"
491 stroke="currentColor"
492 stroke-width="2"
493 stroke-linecap="round"
494 stroke-linejoin="round">
495 <circle cx="12" cy="12" r="3"></circle>
496 <path
497 d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path>
498 </svg>
499 <span>Settings</span>
500 </a>
501
502 <div class="menu-divider"></div>
503
504 <a href="login.html" class="menu-nav-item" style="color: var(--accent-error);" onclick="logout(event)">
505 <svg
506 viewBox="0 0 24 24"
507 fill="none"
508 stroke="currentColor"
509 stroke-width="2"
510 stroke-linecap="round"
511 stroke-linejoin="round">
512 <path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path>
513 <polyline points="16 17 21 12 16 7"></polyline>
514 <line x1="21" y1="12" x2="9" y2="12"></line>
515 </svg>
516 <span>Log Out</span>
517 </a>
518 </div>
519 </nav>
520
521 <!-- Header -->
522 <header class="header">
523 <button class="header-menu-btn" onclick="openMenu()">
524 <svg
525 viewBox="0 0 24 24"
526 fill="none"
527 stroke="currentColor"
528 stroke-width="2"
529 stroke-linecap="round"
530 stroke-linejoin="round">
531 <line x1="3" y1="12" x2="21" y2="12"></line>
532 <line x1="3" y1="6" x2="21" y2="6"></line>
533 <line x1="3" y1="18" x2="21" y2="18"></line>
534 </svg>
535 </button>
536 <h1 class="header-title">Home</h1>
537 <button class="header-action">Settings</button>
538 </header>
539
540 <div class="feed-container">
541 <!-- Compose Box -->
542 <div class="compose-box">
543 <div class="compose-inner">
544 <div class="avatar avatar-sm">JD</div>
545 <div class="compose-input-wrapper">
546 <textarea class="compose-input" placeholder="What's on your mind?" rows="2"></textarea>
547 </div>
548 </div>
549 <div class="compose-actions">
550 <div class="compose-tools">
551 <button class="compose-tool" title="Add image">
552 <svg
553 viewBox="0 0 24 24"
554 fill="none"
555 stroke="currentColor"
556 stroke-width="2"
557 stroke-linecap="round"
558 stroke-linejoin="round">
559 <rect x="3" y="3" width="18" height="18" rx="2" ry="2" />
560 <circle cx="8.5" cy="8.5" r="1.5" />
561 <polyline points="21 15 16 10 5 21" />
562 </svg>
563 </button>
564 <button class="compose-tool" title="Add GIF">
565 <svg
566 viewBox="0 0 24 24"
567 fill="none"
568 stroke="currentColor"
569 stroke-width="2"
570 stroke-linecap="round"
571 stroke-linejoin="round">
572 <text x="4" y="16" font-family="inherit" font-size="12" font-weight="bold" fill="currentColor">
573 GIF
574 </text>
575 </svg>
576 </button>
577 <button class="compose-tool" title="Add poll">
578 <svg
579 viewBox="0 0 24 24"
580 fill="none"
581 stroke="currentColor"
582 stroke-width="2"
583 stroke-linecap="round"
584 stroke-linejoin="round">
585 <line x1="18" y1="20" x2="18" y2="10" />
586 <line x1="12" y1="20" x2="12" y2="4" />
587 <line x1="6" y1="20" x2="6" y2="14" />
588 </svg>
589 </button>
590 <button class="compose-tool" title="Emoji">
591 <svg
592 viewBox="0 0 24 24"
593 fill="none"
594 stroke="currentColor"
595 stroke-width="2"
596 stroke-linecap="round"
597 stroke-linejoin="round">
598 <circle cx="12" cy="12" r="10" />
599 <path d="M8 14s1.5 2 4 2 4-2 4-2" />
600 <line x1="9" y1="9" x2="9.01" y2="9" />
601 <line x1="15" y1="9" x2="15.01" y2="9" />
602 </svg>
603 </button>
604 </div>
605 <button class="compose-submit">Post</button>
606 </div>
607 </div>
608
609 <!-- Feed Tabs -->
610 <div class="feed-tabs">
611 <button class="feed-tab active">Following</button>
612 <button class="feed-tab">Discover</button>
613 </div>
614
615 <!-- Post 1 -->
616 <article class="post-card">
617 <div class="post-header">
618 <div class="avatar">AS</div>
619 <div class="post-author">
620 <div class="post-author-name">Alice Smith</div>
621 <div class="post-author-handle">@alice.bsky.social · <span class="post-timestamp">2h</span></div>
622 </div>
623 </div>
624
625 <div class="post-content">
626 Just launched my new project! 🚀 Check out the demo at <a href="#" class="post-facet-link">example.com</a>.
627 Special thanks to <a href="#" class="post-facet-mention">@bob.bsky.social</a> for the help!
628 <a href="#" class="post-facet-hashtag">#buildinpublic</a> <a href="#" class="post-facet-hashtag">#dev</a>
629 </div>
630
631 <div class="post-embed">
632 <div class="post-embed-image">[Project Screenshot]</div>
633 <div class="post-embed-content">
634 <div class="post-embed-title">My Awesome Project</div>
635 <div class="post-embed-url">example.com</div>
636 </div>
637 </div>
638
639 <div class="post-actions">
640 <button class="post-action">
641 <svg
642 viewBox="0 0 24 24"
643 fill="none"
644 stroke="currentColor"
645 stroke-width="2"
646 stroke-linecap="round"
647 stroke-linejoin="round">
648 <path
649 d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z" />
650 </svg>
651 12
652 </button>
653 <button class="post-action">
654 <svg
655 viewBox="0 0 24 24"
656 fill="none"
657 stroke="currentColor"
658 stroke-width="2"
659 stroke-linecap="round"
660 stroke-linejoin="round">
661 <polyline points="17 1 21 5 17 9" />
662 <path d="M3 11V9a4 4 0 0 1 4-4h14" />
663 <polyline points="7 23 3 19 7 15" />
664 <path d="M21 13v2a4 4 0 0 1-4 4H3" />
665 </svg>
666 5
667 </button>
668 <button class="post-action">
669 <svg
670 viewBox="0 0 24 24"
671 fill="none"
672 stroke="currentColor"
673 stroke-width="2"
674 stroke-linecap="round"
675 stroke-linejoin="round">
676 <path
677 d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" />
678 </svg>
679 48
680 </button>
681 <button class="post-action">
682 <svg
683 viewBox="0 0 24 24"
684 fill="none"
685 stroke="currentColor"
686 stroke-width="2"
687 stroke-linecap="round"
688 stroke-linejoin="round">
689 <path d="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8" />
690 <polyline points="16 6 12 2 8 6" />
691 <line x1="12" y1="2" x2="12" y2="15" />
692 </svg>
693 </button>
694 </div>
695 </article>
696
697 <!-- Post 2 -->
698 <article class="post-card">
699 <div class="post-header">
700 <div class="avatar">BJ</div>
701 <div class="post-author">
702 <div class="post-author-name">Bob Johnson</div>
703 <div class="post-author-handle">@bob.bsky.social · <span class="post-timestamp">4h</span></div>
704 </div>
705 </div>
706
707 <div class="post-content">
708 Working on some exciting features for the next release! Here's a sneak peek of what's coming: improved
709 search, better notifications, and dark mode support. <a href="#" class="post-facet-hashtag">#bluesky</a>
710 <a href="#" class="post-facet-hashtag">#atproto</a>
711 </div>
712
713 <div class="post-actions">
714 <button class="post-action">
715 <svg
716 viewBox="0 0 24 24"
717 fill="none"
718 stroke="currentColor"
719 stroke-width="2"
720 stroke-linecap="round"
721 stroke-linejoin="round">
722 <path
723 d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z" />
724 </svg>
725 8
726 </button>
727 <button class="post-action">
728 <svg
729 viewBox="0 0 24 24"
730 fill="none"
731 stroke="currentColor"
732 stroke-width="2"
733 stroke-linecap="round"
734 stroke-linejoin="round">
735 <polyline points="17 1 21 5 17 9" />
736 <path d="M3 11V9a4 4 0 0 1 4-4h14" />
737 <polyline points="7 23 3 19 7 15" />
738 <path d="M21 13v2a4 4 0 0 1-4 4H3" />
739 </svg>
740 24
741 </button>
742 <button class="post-action">
743 <svg
744 viewBox="0 0 24 24"
745 fill="none"
746 stroke="currentColor"
747 stroke-width="2"
748 stroke-linecap="round"
749 stroke-linejoin="round">
750 <path
751 d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" />
752 </svg>
753 156
754 </button>
755 <button class="post-action">
756 <svg
757 viewBox="0 0 24 24"
758 fill="none"
759 stroke="currentColor"
760 stroke-width="2"
761 stroke-linecap="round"
762 stroke-linejoin="round">
763 <path d="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8" />
764 <polyline points="16 6 12 2 8 6" />
765 <line x1="12" y1="2" x2="12" y2="15" />
766 </svg>
767 </button>
768 </div>
769 </article>
770
771 <!-- Post 3 - Rich Facets -->
772 <article class="post-card">
773 <div class="post-header">
774 <div class="avatar">CW</div>
775 <div class="post-author">
776 <div class="post-author-name">Carol White</div>
777 <div class="post-author-handle">@carol.dev · <span class="post-timestamp">6h</span></div>
778 </div>
779 </div>
780
781 <div class="post-content">
782 The <a href="#" class="post-facet-mention">@atproto</a> team has been doing amazing work! Read their latest
783 blog post about federation: <a href="#" class="post-facet-link">atproto.com/blog/federation</a>
784
785 <br /><br />
786
787 Key highlights: • Self-hosting guides • PDS (Personal Data Server) setup • Relay infrastructure
788
789 <br /><br />
790
791 <a href="#" class="post-facet-hashtag">#atprotocol</a>
792 <a href="#" class="post-facet-hashtag">#decentralized</a>
793 <a href="#" class="post-facet-hashtag">#socialweb</a>
794 </div>
795
796 <div class="post-actions">
797 <button class="post-action">
798 <svg
799 viewBox="0 0 24 24"
800 fill="none"
801 stroke="currentColor"
802 stroke-width="2"
803 stroke-linecap="round"
804 stroke-linejoin="round">
805 <path
806 d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z" />
807 </svg>
808 34
809 </button>
810 <button class="post-action">
811 <svg
812 viewBox="0 0 24 24"
813 fill="none"
814 stroke="currentColor"
815 stroke-width="2"
816 stroke-linecap="round"
817 stroke-linejoin="round">
818 <polyline points="17 1 21 5 17 9" />
819 <path d="M3 11V9a4 4 0 0 1 4-4h14" />
820 <polyline points="7 23 3 19 7 15" />
821 <path d="M21 13v2a4 4 0 0 1-4 4H3" />
822 </svg>
823 12
824 </button>
825 <button class="post-action">
826 <svg
827 viewBox="0 0 24 24"
828 fill="none"
829 stroke="currentColor"
830 stroke-width="2"
831 stroke-linecap="round"
832 stroke-linejoin="round">
833 <path
834 d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" />
835 </svg>
836 289
837 </button>
838 <button class="post-action">
839 <svg
840 viewBox="0 0 24 24"
841 fill="none"
842 stroke="currentColor"
843 stroke-width="2"
844 stroke-linecap="round"
845 stroke-linejoin="round">
846 <path d="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8" />
847 <polyline points="16 6 12 2 8 6" />
848 <line x1="12" y1="2" x2="12" y2="15" />
849 </svg>
850 </button>
851 </div>
852 </article>
853
854 <!-- Post 4 -->
855 <article class="post-card">
856 <div class="post-header">
857 <div class="avatar">DM</div>
858 <div class="post-author">
859 <div class="post-author-name">David Miller</div>
860 <div class="post-author-handle">@davidm.bsky.social · <span class="post-timestamp">8h</span></div>
861 </div>
862 </div>
863
864 <div class="post-content">
865 Beautiful sunset from my hike today! 🌅 <a href="#" class="post-facet-hashtag">#nature</a>
866 <a href="#" class="post-facet-hashtag">#photography</a> <a href="#" class="post-facet-hashtag">#hiking</a>
867 </div>
868
869 <div class="post-embed">
870 <div class="post-embed-image">[Sunset Photo]</div>
871 </div>
872
873 <div class="post-actions">
874 <button class="post-action">
875 <svg
876 viewBox="0 0 24 24"
877 fill="none"
878 stroke="currentColor"
879 stroke-width="2"
880 stroke-linecap="round"
881 stroke-linejoin="round">
882 <path
883 d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z" />
884 </svg>
885 6
886 </button>
887 <button class="post-action">
888 <svg
889 viewBox="0 0 24 24"
890 fill="none"
891 stroke="currentColor"
892 stroke-width="2"
893 stroke-linecap="round"
894 stroke-linejoin="round">
895 <polyline points="17 1 21 5 17 9" />
896 <path d="M3 11V9a4 4 0 0 1 4-4h14" />
897 <polyline points="7 23 3 19 7 15" />
898 <path d="M21 13v2a4 4 0 0 1-4 4H3" />
899 </svg>
900 18
901 </button>
902 <button class="post-action">
903 <svg
904 viewBox="0 0 24 24"
905 fill="none"
906 stroke="currentColor"
907 stroke-width="2"
908 stroke-linecap="round"
909 stroke-linejoin="round">
910 <path
911 d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" />
912 </svg>
913 423
914 </button>
915 <button class="post-action">
916 <svg
917 viewBox="0 0 24 24"
918 fill="none"
919 stroke="currentColor"
920 stroke-width="2"
921 stroke-linecap="round"
922 stroke-linejoin="round">
923 <path d="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8" />
924 <polyline points="16 6 12 2 8 6" />
925 <line x1="12" y1="2" x2="12" y2="15" />
926 </svg>
927 </button>
928 </div>
929 </article>
930 </div>
931
932 <!-- Bottom Navigation -->
933 <nav class="nav-bar">
934 <a href="home.html" class="nav-item active">
935 <svg
936 viewBox="0 0 24 24"
937 fill="none"
938 stroke="currentColor"
939 stroke-width="2"
940 stroke-linecap="round"
941 stroke-linejoin="round">
942 <path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />
943 <polyline points="9 22 9 12 15 12 15 22" />
944 </svg>
945 <span>Home</span>
946 </a>
947
948 <a href="profile.html" class="nav-item">
949 <svg
950 viewBox="0 0 24 24"
951 fill="none"
952 stroke="currentColor"
953 stroke-width="2"
954 stroke-linecap="round"
955 stroke-linejoin="round">
956 <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" />
957 <circle cx="12" cy="7" r="4" />
958 </svg>
959 <span>Profile</span>
960 </a>
961
962 <a href="settings.html" class="nav-item">
963 <svg
964 viewBox="0 0 24 24"
965 fill="none"
966 stroke="currentColor"
967 stroke-width="2"
968 stroke-linecap="round"
969 stroke-linejoin="round">
970 <circle cx="12" cy="12" r="3" />
971 <path
972 d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z" />
973 </svg>
974 <span>Settings</span>
975 </a>
976 </nav>
977 </div>
978
979 <script>
980 function openMenu() {
981 document.getElementById("menuOverlay").classList.add("open");
982 document.getElementById("sideMenu").classList.add("open");
983 }
984
985 function closeMenu() {
986 document.getElementById("menuOverlay").classList.remove("open");
987 document.getElementById("sideMenu").classList.remove("open");
988 }
989
990 function logout(e) {
991 e.preventDefault();
992 if (confirm("Are you sure you want to log out?")) {
993 localStorage.clear();
994 window.location.href = "login.html";
995 }
996 }
997
998 if (localStorage.getItem("theme") === "dark") {
999 document.documentElement.setAttribute("data-theme", "dark");
1000 }
1001 </script>
1002 </body>
1003</html>