mobile bluesky app made with flutter lazurite.stormlightlabs.org/
mobile bluesky flutter
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 897 lines 29 kB view raw
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>Thread - 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 .thread-container { 16 padding-bottom: 88px; 17 } 18 19 /* Thread line connecting parent posts to the focused post */ 20 .thread-line-wrapper { 21 position: relative; 22 } 23 24 .thread-line-wrapper::after { 25 content: ""; 26 position: absolute; 27 left: 39px; /* center of avatar (16px pad + 24px half of 48px avatar) - 1px */ 28 top: 0; 29 bottom: 0; 30 width: 2px; 31 background-color: var(--border); 32 } 33 34 .thread-line-wrapper .post-card { 35 position: relative; 36 z-index: 1; 37 } 38 39 /* Parent post: smaller, muted, with thread line below */ 40 .thread-parent { 41 border-bottom: none; 42 padding-bottom: 0; 43 } 44 45 .thread-parent .post-content { 46 color: var(--text-secondary); 47 } 48 49 .thread-parent .post-actions { 50 display: none; 51 } 52 53 .thread-parent-connector { 54 padding: 0 16px 0 39px; 55 height: 16px; 56 position: relative; 57 } 58 59 .thread-parent-connector::before { 60 content: ""; 61 position: absolute; 62 left: 39px; 63 top: 0; 64 bottom: 0; 65 width: 2px; 66 background-color: var(--border); 67 } 68 69 /* Focused post: the main post in the thread */ 70 .thread-focused { 71 padding: 16px; 72 border-bottom: 1px solid var(--border); 73 background-color: var(--bg); 74 } 75 76 .thread-focused .post-header { 77 display: flex; 78 gap: 12px; 79 margin-bottom: 16px; 80 } 81 82 .thread-focused .post-content { 83 font-size: 17px; 84 line-height: 1.6; 85 color: var(--text-primary); 86 margin-bottom: 16px; 87 } 88 89 .thread-focused-timestamp { 90 font-size: 14px; 91 color: var(--text-muted); 92 padding-bottom: 16px; 93 border-bottom: 1px solid var(--border); 94 margin-bottom: 12px; 95 } 96 97 .thread-focused-stats { 98 display: flex; 99 gap: 20px; 100 padding-bottom: 12px; 101 border-bottom: 1px solid var(--border); 102 margin-bottom: 4px; 103 } 104 105 .thread-stat { 106 font-size: 14px; 107 color: var(--text-secondary); 108 } 109 110 .thread-stat strong { 111 font-weight: 600; 112 color: var(--text-primary); 113 } 114 115 .thread-focused .post-actions { 116 padding-top: 8px; 117 justify-content: space-around; 118 } 119 120 .thread-focused .post-action svg { 121 width: 22px; 122 height: 22px; 123 } 124 125 .thread-focused .post-action { 126 font-size: 0; /* hide counts in focused action bar, they're shown in stats */ 127 } 128 129 /* Active action states */ 130 .post-action.active-like { 131 color: var(--accent-error); 132 } 133 134 .post-action.active-repost { 135 color: var(--accent-success); 136 } 137 138 .post-action.active-bookmark { 139 color: var(--accent-primary); 140 } 141 142 /* Replies section */ 143 .thread-replies-header { 144 padding: 12px 16px 8px; 145 font-size: 13px; 146 font-weight: 600; 147 color: var(--text-muted); 148 text-transform: uppercase; 149 letter-spacing: 0.5px; 150 border-bottom: 1px solid var(--border); 151 } 152 153 /* Nested reply indentation via thread line */ 154 .thread-reply { 155 position: relative; 156 } 157 158 .thread-reply-nested { 159 padding-left: 32px; 160 position: relative; 161 } 162 163 .thread-reply-nested::before { 164 content: ""; 165 position: absolute; 166 left: 39px; 167 top: 0; 168 height: 28px; 169 width: 2px; 170 background-color: var(--border); 171 } 172 173 /* Reply composer fixed at bottom, above nav */ 174 .thread-reply-bar { 175 position: fixed; 176 bottom: 76px; 177 left: 50%; 178 transform: translateX(-50%); 179 width: 100%; 180 max-width: 414px; 181 background-color: var(--surface); 182 border-top: 1px solid var(--border); 183 padding: 10px 16px; 184 display: flex; 185 align-items: center; 186 gap: 12px; 187 z-index: 90; 188 } 189 190 .thread-reply-bar .avatar { 191 width: 32px; 192 height: 32px; 193 font-size: 12px; 194 } 195 196 .thread-reply-input { 197 flex: 1; 198 border: 1px solid var(--border); 199 border-radius: 20px; 200 padding: 8px 16px; 201 font-size: 14px; 202 background-color: var(--bg); 203 color: var(--text-primary); 204 outline: none; 205 font-family: inherit; 206 } 207 208 .thread-reply-input::placeholder { 209 color: var(--text-muted); 210 } 211 212 .thread-reply-input:focus { 213 border-color: var(--accent-primary); 214 } 215 216 .thread-reply-send { 217 width: 36px; 218 height: 36px; 219 border-radius: 50%; 220 border: none; 221 background-color: var(--accent-primary); 222 color: white; 223 cursor: pointer; 224 display: flex; 225 align-items: center; 226 justify-content: center; 227 transition: background-color 0.2s ease; 228 flex-shrink: 0; 229 } 230 231 .thread-reply-send:hover { 232 background-color: var(--accent-primary-hover); 233 } 234 235 .thread-reply-send svg { 236 width: 18px; 237 height: 18px; 238 } 239 240 /* Quoted post embed */ 241 .thread-quote { 242 margin-top: 12px; 243 border: 1px solid var(--border); 244 border-radius: 12px; 245 padding: 12px; 246 } 247 248 .thread-quote-header { 249 display: flex; 250 align-items: center; 251 gap: 8px; 252 margin-bottom: 8px; 253 } 254 255 .thread-quote-avatar { 256 width: 20px; 257 height: 20px; 258 border-radius: 50%; 259 background-color: var(--surface-variant); 260 display: flex; 261 align-items: center; 262 justify-content: center; 263 font-size: 9px; 264 font-weight: 600; 265 color: var(--text-secondary); 266 } 267 268 .thread-quote-author { 269 font-size: 13px; 270 font-weight: 600; 271 color: var(--text-primary); 272 } 273 274 .thread-quote-text { 275 font-size: 13px; 276 color: var(--text-secondary); 277 line-height: 1.4; 278 } 279 280 /* Loading & error states */ 281 .thread-loading { 282 display: flex; 283 flex-direction: column; 284 align-items: center; 285 justify-content: center; 286 padding: 64px 24px; 287 gap: 16px; 288 } 289 290 .thread-spinner { 291 width: 32px; 292 height: 32px; 293 border: 3px solid var(--border); 294 border-top-color: var(--accent-primary); 295 border-radius: 50%; 296 animation: spin 0.8s linear infinite; 297 } 298 299 @keyframes spin { 300 to { 301 transform: rotate(360deg); 302 } 303 } 304 305 .thread-error { 306 display: flex; 307 flex-direction: column; 308 align-items: center; 309 padding: 64px 24px; 310 text-align: center; 311 gap: 12px; 312 } 313 314 .thread-error-icon { 315 width: 48px; 316 height: 48px; 317 color: var(--text-muted); 318 } 319 320 .thread-error-title { 321 font-size: 16px; 322 font-weight: 600; 323 color: var(--text-primary); 324 } 325 326 .thread-error-text { 327 font-size: 14px; 328 color: var(--text-secondary); 329 max-width: 260px; 330 } 331 332 /* Extra bottom padding to account for reply bar */ 333 .thread-container { 334 padding-bottom: 140px; 335 } 336 337 /* Back button */ 338 .header-back { 339 background: none; 340 border: none; 341 color: var(--text-primary); 342 cursor: pointer; 343 padding: 8px; 344 margin-left: -8px; 345 display: flex; 346 align-items: center; 347 } 348 349 .header-back svg { 350 width: 24px; 351 height: 24px; 352 } 353 354 .header-left { 355 display: flex; 356 align-items: center; 357 gap: 8px; 358 } 359 </style> 360 </head> 361 <body> 362 <div class="mobile-container"> 363 <!-- Header --> 364 <header class="header"> 365 <div class="header-left"> 366 <button class="header-back" title="Back"> 367 <svg 368 viewBox="0 0 24 24" 369 fill="none" 370 stroke="currentColor" 371 stroke-width="2" 372 stroke-linecap="round" 373 stroke-linejoin="round"> 374 <line x1="19" y1="12" x2="5" y2="12" /> 375 <polyline points="12 19 5 12 12 5" /> 376 </svg> 377 </button> 378 <h1 class="header-title" style="font-family: var(--font-heading)">Thread</h1> 379 </div> 380 <button class="header-action"> 381 <svg 382 viewBox="0 0 24 24" 383 width="20" 384 height="20" 385 fill="none" 386 stroke="currentColor" 387 stroke-width="2" 388 stroke-linecap="round" 389 stroke-linejoin="round"> 390 <circle cx="12" cy="12" r="1" /> 391 <circle cx="19" cy="12" r="1" /> 392 <circle cx="5" cy="12" r="1" /> 393 </svg> 394 </button> 395 </header> 396 397 <div class="thread-container"> 398 <!-- Parent Post (with thread line) --> 399 <div class="thread-line-wrapper"> 400 <article class="post-card thread-parent"> 401 <div class="post-header"> 402 <div class="avatar">BJ</div> 403 <div class="post-author"> 404 <div class="post-author-name">Bob Johnson</div> 405 <div class="post-author-handle">@bob.bsky.social &middot; <span class="post-timestamp">6h</span></div> 406 </div> 407 </div> 408 <div class="post-content"> 409 What are everyone's thoughts on the latest changes to the AT Protocol? Particularly interested in how 410 federation is being handled. 411 </div> 412 </article> 413 414 <div class="thread-parent-connector"></div> 415 </div> 416 417 <!-- Focused Post (the main post being viewed) --> 418 <article class="thread-focused"> 419 <div class="post-header"> 420 <div class="avatar">AS</div> 421 <div class="post-author"> 422 <div class="post-author-name">Alice Smith</div> 423 <div class="post-author-handle">@alice.bsky.social</div> 424 </div> 425 </div> 426 427 <div class="post-content"> 428 The federation work has been really impressive! The PDS model means you truly own your data. I've been 429 running my own server for a week now and it's been rock solid. 430 <br /><br /> 431 Key things I've noticed:<br /> 432 &bull; Identity is portable across servers<br /> 433 &bull; The relay infrastructure scales well<br /> 434 &bull; App views make custom feeds possible 435 </div> 436 437 <!-- Quoted post embed --> 438 <div class="thread-quote"> 439 <div class="thread-quote-header"> 440 <div class="thread-quote-avatar">AT</div> 441 <span class="thread-quote-author">AT Protocol &middot; @atproto.com</span> 442 </div> 443 <div class="thread-quote-text"> 444 Federation is now live! Self-host your PDS and take control of your social data. Read more at 445 atproto.com/blog/federation 446 </div> 447 </div> 448 449 <div style="height: 16px"></div> 450 451 <div class="thread-focused-timestamp">2:34 PM &middot; Mar 17, 2026</div> 452 453 <div class="thread-focused-stats"> 454 <span class="thread-stat"><strong>24</strong> replies</span> 455 <span class="thread-stat"><strong>12</strong> reposts</span> 456 <span class="thread-stat"><strong>156</strong> likes</span> 457 <span class="thread-stat"><strong>8</strong> saves</span> 458 </div> 459 460 <div class="post-actions"> 461 <!-- Reply --> 462 <button class="post-action"> 463 <svg 464 viewBox="0 0 24 24" 465 fill="none" 466 stroke="currentColor" 467 stroke-width="2" 468 stroke-linecap="round" 469 stroke-linejoin="round"> 470 <path 471 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" /> 472 </svg> 473 </button> 474 <!-- Repost (active) --> 475 <button class="post-action active-repost"> 476 <svg 477 viewBox="0 0 24 24" 478 fill="none" 479 stroke="currentColor" 480 stroke-width="2" 481 stroke-linecap="round" 482 stroke-linejoin="round"> 483 <polyline points="17 1 21 5 17 9" /> 484 <path d="M3 11V9a4 4 0 0 1 4-4h14" /> 485 <polyline points="7 23 3 19 7 15" /> 486 <path d="M21 13v2a4 4 0 0 1-4 4H3" /> 487 </svg> 488 </button> 489 <!-- Like (active) --> 490 <button class="post-action active-like"> 491 <svg viewBox="0 0 24 24" fill="currentColor" stroke="none"> 492 <path 493 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" /> 494 </svg> 495 </button> 496 <!-- Bookmark (active) --> 497 <button class="post-action active-bookmark"> 498 <svg viewBox="0 0 24 24" fill="currentColor" stroke="none"> 499 <path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z" /> 500 </svg> 501 </button> 502 <!-- Share --> 503 <button class="post-action"> 504 <svg 505 viewBox="0 0 24 24" 506 fill="none" 507 stroke="currentColor" 508 stroke-width="2" 509 stroke-linecap="round" 510 stroke-linejoin="round"> 511 <path d="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8" /> 512 <polyline points="16 6 12 2 8 6" /> 513 <line x1="12" y1="2" x2="12" y2="15" /> 514 </svg> 515 </button> 516 </div> 517 </article> 518 519 <!-- Replies --> 520 <div class="thread-replies-header">Replies</div> 521 522 <!-- Reply 1 --> 523 <article class="post-card thread-reply"> 524 <div class="post-header"> 525 <div class="avatar">CW</div> 526 <div class="post-author"> 527 <div class="post-author-name">Carol White</div> 528 <div class="post-author-handle">@carol.dev &middot; <span class="post-timestamp">4h</span></div> 529 </div> 530 </div> 531 <div class="post-content"> 532 This is spot on! The portability aspect is what sold me. Being able to migrate my entire social presence 533 without losing followers is a game changer. 534 </div> 535 <div class="post-actions"> 536 <button class="post-action"> 537 <svg 538 viewBox="0 0 24 24" 539 fill="none" 540 stroke="currentColor" 541 stroke-width="2" 542 stroke-linecap="round" 543 stroke-linejoin="round"> 544 <path 545 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" /> 546 </svg> 547 3 548 </button> 549 <button class="post-action"> 550 <svg 551 viewBox="0 0 24 24" 552 fill="none" 553 stroke="currentColor" 554 stroke-width="2" 555 stroke-linecap="round" 556 stroke-linejoin="round"> 557 <polyline points="17 1 21 5 17 9" /> 558 <path d="M3 11V9a4 4 0 0 1 4-4h14" /> 559 <polyline points="7 23 3 19 7 15" /> 560 <path d="M21 13v2a4 4 0 0 1-4 4H3" /> 561 </svg> 562 1 563 </button> 564 <button class="post-action active-like"> 565 <svg viewBox="0 0 24 24" fill="currentColor" stroke="none"> 566 <path 567 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" /> 568 </svg> 569 18 570 </button> 571 <button class="post-action"> 572 <svg 573 viewBox="0 0 24 24" 574 fill="none" 575 stroke="currentColor" 576 stroke-width="2" 577 stroke-linecap="round" 578 stroke-linejoin="round"> 579 <path d="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8" /> 580 <polyline points="16 6 12 2 8 6" /> 581 <line x1="12" y1="2" x2="12" y2="15" /> 582 </svg> 583 </button> 584 </div> 585 </article> 586 587 <!-- Reply 2 (with nested sub-reply) --> 588 <article class="post-card thread-reply"> 589 <div class="post-header"> 590 <div class="avatar">DM</div> 591 <div class="post-author"> 592 <div class="post-author-name">David Miller</div> 593 <div class="post-author-handle">@davidm.bsky.social &middot; <span class="post-timestamp">3h</span></div> 594 </div> 595 </div> 596 <div class="post-content"> 597 Have you run into any performance issues with your PDS? I'm considering self-hosting but worried about the 598 resource requirements. 599 </div> 600 <div class="post-actions"> 601 <button class="post-action"> 602 <svg 603 viewBox="0 0 24 24" 604 fill="none" 605 stroke="currentColor" 606 stroke-width="2" 607 stroke-linecap="round" 608 stroke-linejoin="round"> 609 <path 610 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" /> 611 </svg> 612 1 613 </button> 614 <button class="post-action"> 615 <svg 616 viewBox="0 0 24 24" 617 fill="none" 618 stroke="currentColor" 619 stroke-width="2" 620 stroke-linecap="round" 621 stroke-linejoin="round"> 622 <polyline points="17 1 21 5 17 9" /> 623 <path d="M3 11V9a4 4 0 0 1 4-4h14" /> 624 <polyline points="7 23 3 19 7 15" /> 625 <path d="M21 13v2a4 4 0 0 1-4 4H3" /> 626 </svg> 627 </button> 628 <button class="post-action"> 629 <svg 630 viewBox="0 0 24 24" 631 fill="none" 632 stroke="currentColor" 633 stroke-width="2" 634 stroke-linecap="round" 635 stroke-linejoin="round"> 636 <path 637 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" /> 638 </svg> 639 5 640 </button> 641 <button class="post-action"> 642 <svg 643 viewBox="0 0 24 24" 644 fill="none" 645 stroke="currentColor" 646 stroke-width="2" 647 stroke-linecap="round" 648 stroke-linejoin="round"> 649 <path d="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8" /> 650 <polyline points="16 6 12 2 8 6" /> 651 <line x1="12" y1="2" x2="12" y2="15" /> 652 </svg> 653 </button> 654 </div> 655 </article> 656 657 <!-- Reply 3: Author's own reply in thread --> 658 <article class="post-card thread-reply thread-reply-nested"> 659 <div class="post-header"> 660 <div class="avatar">AS</div> 661 <div class="post-author"> 662 <div class="post-author-name">Alice Smith</div> 663 <div class="post-author-handle">@alice.bsky.social &middot; <span class="post-timestamp">2h</span></div> 664 </div> 665 </div> 666 <div class="post-content"> 667 Runs great on a small VPS! I'm using a 2GB instance and it handles everything smoothly. The docs have a good 668 guide on minimal setups. 669 </div> 670 <div class="post-actions"> 671 <button class="post-action"> 672 <svg 673 viewBox="0 0 24 24" 674 fill="none" 675 stroke="currentColor" 676 stroke-width="2" 677 stroke-linecap="round" 678 stroke-linejoin="round"> 679 <path 680 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" /> 681 </svg> 682 </button> 683 <button class="post-action"> 684 <svg 685 viewBox="0 0 24 24" 686 fill="none" 687 stroke="currentColor" 688 stroke-width="2" 689 stroke-linecap="round" 690 stroke-linejoin="round"> 691 <polyline points="17 1 21 5 17 9" /> 692 <path d="M3 11V9a4 4 0 0 1 4-4h14" /> 693 <polyline points="7 23 3 19 7 15" /> 694 <path d="M21 13v2a4 4 0 0 1-4 4H3" /> 695 </svg> 696 </button> 697 <button class="post-action"> 698 <svg 699 viewBox="0 0 24 24" 700 fill="none" 701 stroke="currentColor" 702 stroke-width="2" 703 stroke-linecap="round" 704 stroke-linejoin="round"> 705 <path 706 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" /> 707 </svg> 708 12 709 </button> 710 <button class="post-action"> 711 <svg 712 viewBox="0 0 24 24" 713 fill="none" 714 stroke="currentColor" 715 stroke-width="2" 716 stroke-linecap="round" 717 stroke-linejoin="round"> 718 <path d="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8" /> 719 <polyline points="16 6 12 2 8 6" /> 720 <line x1="12" y1="2" x2="12" y2="15" /> 721 </svg> 722 </button> 723 </div> 724 </article> 725 726 <!-- Reply 4 --> 727 <article class="post-card thread-reply"> 728 <div class="post-header"> 729 <div class="avatar">EL</div> 730 <div class="post-author"> 731 <div class="post-author-name">Eva Lee</div> 732 <div class="post-author-handle">@eva.bsky.social &middot; <span class="post-timestamp">1h</span></div> 733 </div> 734 </div> 735 <div class="post-content"> 736 The custom feeds through app views are my favourite part. Being able to build your own algorithmic timeline 737 without depending on the platform is so empowering. 738 <a href="#" class="post-facet-hashtag">#atproto</a> <a href="#" class="post-facet-hashtag">#openweb</a> 739 </div> 740 <div class="post-actions"> 741 <button class="post-action"> 742 <svg 743 viewBox="0 0 24 24" 744 fill="none" 745 stroke="currentColor" 746 stroke-width="2" 747 stroke-linecap="round" 748 stroke-linejoin="round"> 749 <path 750 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" /> 751 </svg> 752 2 753 </button> 754 <button class="post-action"> 755 <svg 756 viewBox="0 0 24 24" 757 fill="none" 758 stroke="currentColor" 759 stroke-width="2" 760 stroke-linecap="round" 761 stroke-linejoin="round"> 762 <polyline points="17 1 21 5 17 9" /> 763 <path d="M3 11V9a4 4 0 0 1 4-4h14" /> 764 <polyline points="7 23 3 19 7 15" /> 765 <path d="M21 13v2a4 4 0 0 1-4 4H3" /> 766 </svg> 767 4 768 </button> 769 <button class="post-action"> 770 <svg 771 viewBox="0 0 24 24" 772 fill="none" 773 stroke="currentColor" 774 stroke-width="2" 775 stroke-linecap="round" 776 stroke-linejoin="round"> 777 <path 778 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" /> 779 </svg> 780 31 781 </button> 782 <button class="post-action"> 783 <svg 784 viewBox="0 0 24 24" 785 fill="none" 786 stroke="currentColor" 787 stroke-width="2" 788 stroke-linecap="round" 789 stroke-linejoin="round"> 790 <path d="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8" /> 791 <polyline points="16 6 12 2 8 6" /> 792 <line x1="12" y1="2" x2="12" y2="15" /> 793 </svg> 794 </button> 795 </div> 796 </article> 797 </div> 798 799 <!-- Reply Composer Bar --> 800 <div class="thread-reply-bar"> 801 <div class="avatar" style="width: 32px; height: 32px; font-size: 12px">JD</div> 802 <input type="text" class="thread-reply-input" placeholder="Reply to Alice..." /> 803 <button class="thread-reply-send" title="Send reply"> 804 <svg 805 viewBox="0 0 24 24" 806 fill="none" 807 stroke="currentColor" 808 stroke-width="2" 809 stroke-linecap="round" 810 stroke-linejoin="round"> 811 <line x1="22" y1="2" x2="11" y2="13" /> 812 <polygon points="22 2 15 22 11 13 2 9 22 2" /> 813 </svg> 814 </button> 815 </div> 816 817 <!-- Bottom Navigation --> 818 <nav class="nav-bar"> 819 <a href="home.html" class="nav-item"> 820 <svg 821 viewBox="0 0 24 24" 822 fill="none" 823 stroke="currentColor" 824 stroke-width="2" 825 stroke-linecap="round" 826 stroke-linejoin="round"> 827 <path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" /> 828 <polyline points="9 22 9 12 15 12 15 22" /> 829 </svg> 830 <span>Home</span> 831 </a> 832 833 <a href="search.html" class="nav-item"> 834 <svg 835 viewBox="0 0 24 24" 836 fill="none" 837 stroke="currentColor" 838 stroke-width="2" 839 stroke-linecap="round" 840 stroke-linejoin="round"> 841 <circle cx="11" cy="11" r="8" /> 842 <line x1="21" y1="21" x2="16.65" y2="16.65" /> 843 </svg> 844 <span>Search</span> 845 </a> 846 847 <a href="notifications.html" class="nav-item"> 848 <svg 849 viewBox="0 0 24 24" 850 fill="none" 851 stroke="currentColor" 852 stroke-width="2" 853 stroke-linecap="round" 854 stroke-linejoin="round"> 855 <path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9" /> 856 <path d="M13.73 21a2 2 0 0 1-3.46 0" /> 857 </svg> 858 <span>Alerts</span> 859 </a> 860 861 <a href="messages.html" class="nav-item"> 862 <svg 863 viewBox="0 0 24 24" 864 fill="none" 865 stroke="currentColor" 866 stroke-width="2" 867 stroke-linecap="round" 868 stroke-linejoin="round"> 869 <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" /> 870 </svg> 871 <span>Chat</span> 872 </a> 873 874 <a href="profile.html" class="nav-item"> 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 d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" /> 883 <circle cx="12" cy="7" r="4" /> 884 </svg> 885 <span>Profile</span> 886 </a> 887 </nav> 888 </div> 889 890 <script> 891 if (localStorage.getItem("theme")) { 892 const t = localStorage.getItem("theme"); 893 if (t !== "light") document.documentElement.setAttribute("data-theme", t); 894 } 895 </script> 896 </body> 897</html>