This repository has no description
0

Configure Feed

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

stigmergic / src / landing-page.ts
21 kB 831 lines
1export const LANDING_PAGE = `<!DOCTYPE html> 2<html lang="en"> 3<head> 4 <meta charset="utf-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1"> 6 <title>Stigmergic</title> 7 <style> 8 :root { 9 --bg: #0d1117; 10 --surface: #161b22; 11 --border: #30363d; 12 --text: #e6edf3; 13 --text-muted: #8b949e; 14 --accent: #58a6ff; 15 --accent-hover: #79c0ff; 16 --green: #3fb950; 17 --red: #f85149; 18 --yellow: #d29922; 19 --purple: #bc8cff; 20 } 21 * { margin: 0; padding: 0; box-sizing: border-box; } 22 body { 23 font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif; 24 background: var(--bg); 25 color: var(--text); 26 line-height: 1.6; 27 min-height: 100vh; 28 } 29 header { 30 border-bottom: 1px solid var(--border); 31 padding: 1rem 2rem; 32 display: flex; 33 align-items: center; 34 justify-content: space-between; 35 } 36 header h1 { 37 font-size: 1.25rem; 38 font-weight: 600; 39 color: var(--accent); 40 } 41 header nav { display: flex; gap: 1rem; align-items: center; } 42 header nav a, header nav button { 43 color: var(--text-muted); 44 text-decoration: none; 45 font-size: 0.875rem; 46 background: none; 47 border: none; 48 cursor: pointer; 49 padding: 0.25rem 0.75rem; 50 border-radius: 6px; 51 } 52 header nav a:hover, header nav button:hover { 53 color: var(--text); 54 background: var(--surface); 55 } 56 main { 57 max-width: 960px; 58 margin: 0 auto; 59 padding: 2rem; 60 } 61 .search-bar { 62 display: flex; 63 max-width: 480px; 64 margin: 0 auto 2rem; 65 } 66 .search-bar input { 67 flex: 1; 68 padding: 0.625rem 1rem; 69 border: 1px solid var(--border); 70 border-radius: 6px 0 0 6px; 71 background: var(--surface); 72 color: var(--text); 73 font-size: 0.875rem; 74 outline: none; 75 } 76 .search-bar input:focus { border-color: var(--accent); } 77 .search-bar button { 78 padding: 0.625rem 1.25rem; 79 background: var(--accent); 80 color: #fff; 81 border: none; 82 border-radius: 0 6px 6px 0; 83 cursor: pointer; 84 font-size: 0.875rem; 85 font-weight: 500; 86 } 87 .search-bar button:hover { background: var(--accent-hover); } 88 .search-hint { 89 text-align: center; 90 color: var(--text-muted); 91 font-size: 0.75rem; 92 margin-bottom: 2rem; 93 } 94 95 /* Explore layout */ 96 .explore-page { 97 display: grid; 98 grid-template-columns: 1fr 240px; 99 gap: 2rem; 100 } 101 .explore-header { 102 display: flex; 103 justify-content: space-between; 104 align-items: center; 105 margin-bottom: 1rem; 106 } 107 .explore-header h2 { 108 font-size: 1.25rem; 109 color: var(--text); 110 } 111 .explore-sidebar h3 { 112 font-size: 0.875rem; 113 color: var(--text-muted); 114 margin-bottom: 0.75rem; 115 } 116 .collections-sidebar { 117 display: flex; 118 flex-direction: column; 119 gap: 0.5rem; 120 } 121 .sidebar-collection { 122 display: flex; 123 flex-direction: column; 124 padding: 0.5rem 0.75rem; 125 border-radius: 6px; 126 text-decoration: none; 127 color: inherit; 128 border: 1px solid transparent; 129 } 130 .sidebar-collection:hover { 131 background: var(--surface); 132 border-color: var(--border); 133 } 134 .sidebar-name { font-size: 0.8125rem; font-weight: 500; } 135 .sidebar-handle { font-size: 0.6875rem; color: var(--text-muted); } 136 .sidebar-empty { color: var(--text-muted); font-size: 0.75rem; } 137 138 /* Face feed */ 139 .face-feed { 140 display: flex; 141 flex-direction: column; 142 gap: 1rem; 143 } 144 .face-card { 145 background: var(--surface); 146 border: 1px solid var(--border); 147 border-radius: 10px; 148 padding: 1rem 1.25rem; 149 transition: border-color 0.15s; 150 } 151 .face-card:hover { border-color: var(--accent); } 152 .face-top { 153 display: flex; 154 justify-content: space-between; 155 align-items: flex-start; 156 gap: 0.75rem; 157 margin-bottom: 0.5rem; 158 } 159 .face-header { 160 display: flex; 161 align-items: flex-start; 162 gap: 0.625rem; 163 text-decoration: none; 164 color: inherit; 165 flex: 1; 166 min-width: 0; 167 } 168 .face-header:hover .face-title { color: var(--accent); } 169 .face-favicon { 170 width: 20px; 171 height: 20px; 172 border-radius: 3px; 173 margin-top: 2px; 174 flex-shrink: 0; 175 } 176 .face-title-block { min-width: 0; } 177 .face-title { 178 font-size: 0.9375rem; 179 font-weight: 600; 180 color: var(--text); 181 line-height: 1.3; 182 overflow: hidden; 183 text-overflow: ellipsis; 184 white-space: nowrap; 185 } 186 .face-site { 187 font-size: 0.6875rem; 188 color: var(--text-muted); 189 } 190 .face-actions { 191 display: flex; 192 align-items: center; 193 gap: 0.5rem; 194 flex-shrink: 0; 195 } 196 .face-degree { 197 font-size: 0.625rem; 198 padding: 0.125rem 0.375rem; 199 border-radius: 8px; 200 background: var(--border); 201 color: var(--text-muted); 202 font-weight: 600; 203 } 204 .face-action-btn { 205 color: var(--text-muted); 206 font-size: 0.6875rem; 207 text-decoration: none; 208 } 209 .face-action-btn:hover { color: var(--accent); } 210 .face-desc { 211 font-size: 0.8125rem; 212 color: var(--text-muted); 213 line-height: 1.4; 214 margin-bottom: 0.75rem; 215 overflow: hidden; 216 text-overflow: ellipsis; 217 display: -webkit-box; 218 -webkit-line-clamp: 2; 219 -webkit-box-orient: vertical; 220 } 221 222 /* Face edges */ 223 .face-edges { 224 display: flex; 225 gap: 1rem; 226 flex-wrap: wrap; 227 } 228 .face-neighbors { 229 flex: 1; 230 min-width: 200px; 231 } 232 .face-neighbors.incoming { 233 border-left: 2px solid var(--green); 234 padding-left: 0.75rem; 235 } 236 .face-neighbors.outgoing { 237 border-left: 2px solid var(--accent); 238 padding-left: 0.75rem; 239 } 240 .neighbors-label { 241 font-size: 0.625rem; 242 color: var(--text-muted); 243 text-transform: uppercase; 244 letter-spacing: 0.05em; 245 margin-bottom: 0.375rem; 246 font-weight: 600; 247 } 248 .face-neighbors.incoming .neighbors-label { color: var(--green); } 249 .face-neighbors.outgoing .neighbors-label { color: var(--accent); } 250 .neighbors-list { 251 display: flex; 252 flex-direction: column; 253 gap: 0.25rem; 254 } 255 .neighbor-pill { 256 display: flex; 257 align-items: center; 258 gap: 0.375rem; 259 text-decoration: none; 260 color: inherit; 261 padding: 0.25rem 0.5rem; 262 border-radius: 6px; 263 background: var(--bg); 264 border: 1px solid transparent; 265 transition: border-color 0.1s; 266 } 267 .neighbor-pill:hover { border-color: var(--border); } 268 .neighbor-pill:hover .pill-title { color: var(--accent); } 269 .pill-favicon { 270 width: 14px; 271 height: 14px; 272 border-radius: 2px; 273 flex-shrink: 0; 274 } 275 .pill-type { 276 font-size: 0.625rem; 277 color: var(--text-muted); 278 flex-shrink: 0; 279 } 280 .pill-title { 281 font-size: 0.75rem; 282 color: var(--text); 283 overflow: hidden; 284 text-overflow: ellipsis; 285 white-space: nowrap; 286 } 287 288 /* Connection items (resource page) */ 289 .connection-item { 290 background: var(--surface); 291 border: 1px solid var(--border); 292 border-radius: 8px; 293 padding: 1rem 1.25rem; 294 transition: border-color 0.15s; 295 } 296 .connection-item:hover { border-color: var(--accent); } 297 .connection-item.compact { 298 padding: 0.5rem 0.75rem; 299 display: flex; 300 align-items: center; 301 gap: 0.5rem; 302 flex-wrap: wrap; 303 background: var(--bg); 304 border-radius: 6px; 305 } 306 .conn-type-badge { 307 font-size: 0.6875rem; 308 padding: 0.125rem 0.5rem; 309 border-radius: 12px; 310 background: var(--border); 311 color: var(--text); 312 } 313 .conn-uri { 314 color: var(--accent); 315 text-decoration: none; 316 font-size: 0.875rem; 317 font-weight: 500; 318 word-break: break-all; 319 } 320 .conn-uri:hover { text-decoration: underline; } 321 .conn-site { 322 font-size: 0.625rem; 323 color: var(--text-muted); 324 } 325 .conn-note-inline { 326 color: var(--text-muted); 327 font-size: 0.75rem; 328 } 329 .conn-handle-inline { 330 color: var(--text-muted); 331 font-size: 0.6875rem; 332 margin-left: auto; 333 } 334 335 /* Resource page header card */ 336 .resource-header-card { 337 display: flex; 338 gap: 1rem; 339 padding: 1.25rem; 340 background: var(--surface); 341 border: 1px solid var(--border); 342 border-radius: 8px; 343 margin-bottom: 1rem; 344 } 345 .resource-favicon { 346 width: 32px; 347 height: 32px; 348 border-radius: 4px; 349 flex-shrink: 0; 350 } 351 .resource-meta { min-width: 0; } 352 .resource-title { 353 font-size: 1.125rem; 354 font-weight: 600; 355 color: var(--text); 356 margin-bottom: 0.25rem; 357 line-height: 1.3; 358 } 359 .resource-site { 360 font-size: 0.75rem; 361 color: var(--text-muted); 362 margin-bottom: 0.375rem; 363 } 364 .resource-desc { 365 font-size: 0.8125rem; 366 color: var(--text-muted); 367 line-height: 1.4; 368 } 369 370 /* Strata button */ 371 .strata-btn { 372 background: none; 373 border: 1px solid var(--purple); 374 color: var(--purple); 375 font-size: 0.6875rem; 376 padding: 0.125rem 0.5rem; 377 border-radius: 4px; 378 cursor: pointer; 379 font-weight: 500; 380 } 381 .strata-btn:hover { background: var(--purple); color: #fff; } 382 .strata-btn.compact { 383 font-size: 0.625rem; 384 padding: 0.0625rem 0.375rem; 385 margin-left: auto; 386 } 387 388 /* Modal */ 389 .modal-overlay { 390 position: fixed; 391 top: 0; left: 0; right: 0; bottom: 0; 392 background: rgba(0,0,0,0.6); 393 display: flex; 394 align-items: center; 395 justify-content: center; 396 z-index: 1000; 397 } 398 .modal-content { 399 background: var(--surface); 400 border: 1px solid var(--border); 401 border-radius: 12px; 402 max-width: 560px; 403 width: 90%; 404 max-height: 80vh; 405 overflow-y: auto; 406 padding: 1.5rem; 407 } 408 .modal-header { 409 display: flex; 410 justify-content: space-between; 411 align-items: center; 412 margin-bottom: 1rem; 413 } 414 .modal-header h2 { 415 font-size: 1rem; 416 color: var(--purple); 417 } 418 .modal-close { 419 background: none; 420 border: none; 421 color: var(--text-muted); 422 font-size: 1.5rem; 423 cursor: pointer; 424 line-height: 1; 425 } 426 .modal-close:hover { color: var(--text); } 427 428 /* Analysis results */ 429 .analysis-loading { 430 text-align: center; 431 color: var(--text-muted); 432 padding: 2rem; 433 } 434 .spinner { 435 width: 24px; 436 height: 24px; 437 border: 2px solid var(--border); 438 border-top-color: var(--purple); 439 border-radius: 50%; 440 animation: spin 0.8s linear infinite; 441 margin: 0 auto 0.75rem; 442 } 443 @keyframes spin { to { transform: rotate(360deg); } } 444 445 .analysis-section { 446 margin-bottom: 1.25rem; 447 } 448 .analysis-section h3 { 449 font-size: 0.875rem; 450 color: var(--text-muted); 451 margin-bottom: 0.5rem; 452 } 453 .citation-card { 454 background: var(--bg); 455 border: 1px solid var(--border); 456 border-radius: 6px; 457 padding: 1rem; 458 } 459 .citation-title { 460 font-size: 0.9375rem; 461 font-weight: 600; 462 color: var(--text); 463 margin-bottom: 0.25rem; 464 } 465 .citation-url { 466 font-size: 0.75rem; 467 color: var(--accent); 468 margin-bottom: 0.5rem; 469 word-break: break-all; 470 } 471 .citation-takeaway { 472 font-size: 0.8125rem; 473 color: var(--text-muted); 474 line-height: 1.4; 475 margin-bottom: 0.5rem; 476 } 477 .citation-meta { 478 display: flex; 479 gap: 0.75rem; 480 align-items: center; 481 margin-bottom: 0.5rem; 482 } 483 .citation-domain { 484 font-size: 0.6875rem; 485 color: var(--text-muted); 486 } 487 .citation-confidence { 488 font-size: 0.625rem; 489 padding: 0.0625rem 0.375rem; 490 border-radius: 8px; 491 font-weight: 500; 492 } 493 .citation-confidence.high { background: #1a3a1a; color: var(--green); } 494 .citation-confidence.medium { background: #3a2a1a; color: var(--yellow); } 495 .citation-confidence.low { background: #3a1a1a; color: var(--red); } 496 .citation-tags { 497 display: flex; 498 gap: 0.25rem; 499 flex-wrap: wrap; 500 } 501 .tag { 502 font-size: 0.625rem; 503 padding: 0.0625rem 0.375rem; 504 border-radius: 8px; 505 background: var(--border); 506 color: var(--text-muted); 507 } 508 .citation-record { 509 font-size: 0.75rem; 510 background: var(--bg); 511 border: 1px solid var(--border); 512 border-radius: 6px; 513 padding: 0.75rem; 514 overflow-x: auto; 515 color: var(--text-muted); 516 } 517 .analysis-error { 518 color: var(--red); 519 padding: 1rem; 520 text-align: center; 521 } 522 523 /* Strata analysis button */ 524 .strata-btn { 525 display: inline-flex; 526 align-items: center; 527 gap: 0.375rem; 528 padding: 0.375rem 0.75rem; 529 border-radius: 6px; 530 font-size: 0.75rem; 531 font-weight: 500; 532 background: var(--purple); 533 color: #fff; 534 border: none; 535 cursor: pointer; 536 text-decoration: none; 537 } 538 .strata-btn:hover { opacity: 0.9; } 539 .strata-btn:disabled { opacity: 0.5; cursor: wait; } 540 541 /* Strata analysis modal */ 542 .modal-overlay { 543 position: fixed; 544 inset: 0; 545 background: rgba(0,0,0,0.6); 546 z-index: 100; 547 display: flex; 548 align-items: center; 549 justify-content: center; 550 } 551 .modal-content { 552 background: var(--surface); 553 border: 1px solid var(--border); 554 border-radius: 12px; 555 padding: 2rem; 556 max-width: 640px; 557 width: 90%; 558 max-height: 80vh; 559 overflow-y: auto; 560 } 561 .modal-header { 562 display: flex; 563 justify-content: space-between; 564 align-items: center; 565 margin-bottom: 1.5rem; 566 } 567 .modal-header h2 { font-size: 1.125rem; color: var(--purple); } 568 .modal-close { 569 background: none; 570 border: none; 571 color: var(--text-muted); 572 font-size: 1.25rem; 573 cursor: pointer; 574 } 575 .modal-close:hover { color: var(--text); } 576 .analysis-section { margin-bottom: 1.5rem; } 577 .analysis-section h3 { 578 font-size: 0.875rem; 579 color: var(--text-muted); 580 margin-bottom: 0.5rem; 581 } 582 .theme-tags { display: flex; flex-wrap: wrap; gap: 0.375rem; } 583 .theme-tag { 584 padding: 0.25rem 0.625rem; 585 border-radius: 12px; 586 background: var(--border); 587 color: var(--text); 588 font-size: 0.75rem; 589 } 590 .analysis-connection { 591 padding: 0.5rem 0.75rem; 592 border: 1px solid var(--border); 593 border-radius: 6px; 594 margin-bottom: 0.5rem; 595 font-size: 0.8125rem; 596 } 597 .analysis-connection .relation { 598 color: var(--purple); 599 font-weight: 500; 600 font-size: 0.6875rem; 601 } 602 .analysis-tension { 603 padding: 0.5rem 0.75rem; 604 border-left: 3px solid var(--red); 605 background: rgba(248,81,73,0.05); 606 border-radius: 0 6px 6px 0; 607 margin-bottom: 0.5rem; 608 font-size: 0.8125rem; 609 } 610 .analysis-question { 611 padding: 0.5rem 0.75rem; 612 border-left: 3px solid var(--yellow); 613 background: rgba(210,153,34,0.05); 614 border-radius: 0 6px 6px 0; 615 margin-bottom: 0.5rem; 616 font-size: 0.8125rem; 617 } 618 .synthesis-text { 619 font-size: 0.875rem; 620 line-height: 1.7; 621 color: var(--text); 622 } 623 .carry-ref { 624 display: inline-flex; 625 align-items: center; 626 gap: 0.25rem; 627 padding: 0.25rem 0.5rem; 628 border-radius: 4px; 629 background: var(--surface); 630 border: 1px solid var(--border); 631 font-size: 0.6875rem; 632 color: var(--text-muted); 633 margin: 0.25rem; 634 } 635 .analysis-loading { 636 text-align: center; 637 padding: 2rem; 638 color: var(--text-muted); 639 } 640 .analysis-loading .spinner { 641 display: inline-block; 642 width: 24px; 643 height: 24px; 644 border: 2px solid var(--border); 645 border-top-color: var(--purple); 646 border-radius: 50%; 647 animation: spin 0.8s linear infinite; 648 margin-bottom: 0.75rem; 649 } 650 @keyframes spin { to { transform: rotate(360deg); } } 651 652 /* Resource page */ 653 .resource-page { } 654 .resource-uri { 655 font-size: 1rem; 656 color: var(--accent); 657 word-break: break-all; 658 margin-bottom: 1rem; 659 padding: 0.75rem 1rem; 660 background: var(--surface); 661 border: 1px solid var(--border); 662 border-radius: 6px; 663 } 664 .resource-actions { 665 display: flex; 666 gap: 0.75rem; 667 margin-bottom: 2rem; 668 } 669 .yoneda-section { 670 margin-bottom: 2rem; 671 } 672 .yoneda-section h3 { 673 font-size: 1rem; 674 margin-bottom: 0.75rem; 675 } 676 .yoneda-hint { 677 font-size: 0.6875rem; 678 color: var(--text-muted); 679 font-weight: 400; 680 } 681 .connection-list { 682 display: flex; 683 flex-direction: column; 684 gap: 0.5rem; 685 } 686 687 /* Graph page */ 688 .graph-page { } 689 .graph-meta { 690 color: var(--text-muted); 691 font-size: 0.875rem; 692 margin-bottom: 2rem; 693 } 694 .graph-connections, .graph-nodes { 695 margin-bottom: 2rem; 696 } 697 .graph-connections h3, .graph-nodes h3 { 698 font-size: 1rem; 699 margin-bottom: 0.75rem; 700 } 701 .graph-node { 702 display: inline-block; 703 padding: 0.375rem 0.75rem; 704 margin: 0.25rem; 705 background: var(--surface); 706 border: 1px solid var(--border); 707 border-radius: 6px; 708 color: var(--accent); 709 text-decoration: none; 710 font-size: 0.8125rem; 711 } 712 .graph-node:hover { border-color: var(--accent); } 713 714 /* Connect page */ 715 .connect-page { max-width: 600px; } 716 .connect-hint { 717 color: var(--text-muted); 718 font-size: 0.875rem; 719 margin-bottom: 1.5rem; 720 } 721 .connect-form { 722 display: flex; 723 flex-direction: column; 724 gap: 1rem; 725 } 726 .form-field { 727 display: flex; 728 flex-direction: column; 729 gap: 0.25rem; 730 } 731 .form-field label { 732 font-size: 0.875rem; 733 font-weight: 500; 734 } 735 .form-field input, .form-field textarea, .form-field select { 736 padding: 0.625rem 0.75rem; 737 border: 1px solid var(--border); 738 border-radius: 6px; 739 background: var(--surface); 740 color: var(--text); 741 font-size: 0.875rem; 742 outline: none; 743 font-family: inherit; 744 } 745 .form-field input:focus, .form-field textarea:focus, .form-field select:focus { 746 border-color: var(--accent); 747 } 748 .form-field textarea { resize: vertical; min-height: 80px; } 749 .form-actions { 750 display: flex; 751 gap: 0.75rem; 752 } 753 .action-btn { 754 display: inline-block; 755 padding: 0.5rem 1rem; 756 border-radius: 6px; 757 font-size: 0.875rem; 758 font-weight: 500; 759 text-decoration: none; 760 cursor: pointer; 761 background: var(--surface); 762 border: 1px solid var(--border); 763 color: var(--text); 764 } 765 .action-btn:hover { border-color: var(--accent); color: var(--accent); } 766 .action-btn.primary { 767 background: var(--accent); 768 border-color: var(--accent); 769 color: #fff; 770 } 771 .action-btn.primary:hover { background: var(--accent-hover); } 772 .connect-result { 773 margin-top: 1rem; 774 } 775 .connect-result pre { 776 background: var(--surface); 777 border: 1px solid var(--border); 778 border-radius: 6px; 779 padding: 1rem; 780 font-size: 0.8125rem; 781 overflow-x: auto; 782 } 783 .preview-hint { 784 color: var(--text-muted); 785 font-size: 0.75rem; 786 margin-top: 0.5rem; 787 } 788 .pending { color: var(--yellow); } 789 790 /* Shared */ 791 .back-link { 792 color: var(--accent); 793 text-decoration: none; 794 font-size: 0.875rem; 795 display: inline-block; 796 margin-right: 1rem; 797 margin-bottom: 1rem; 798 } 799 .back-link:hover { text-decoration: underline; } 800 .empty { 801 text-align: center; 802 padding: 2rem; 803 color: var(--text-muted); 804 } 805 #auth-status { display: none; } 806 #auth-status.visible { display: inline; } 807 #login-btn { display: inline; } 808 #login-btn.hidden { display: none; } 809 </style> 810</head> 811<body> 812 <header> 813 <h1>Stigmergic</h1> 814 <nav> 815 <a href="/">Explore</a> 816 <a href="/connect">Connect</a> 817 <span id="auth-status" class="visible"></span> 818 <button id="login-btn">Sign in</button> 819 </nav> 820 </header> 821 <main> 822 <div class="search-bar"> 823 <input type="text" id="search-input" placeholder="Enter a URL or AT URI to explore..."> 824 <button id="search-btn">Go</button> 825 </div> 826 <div class="search-hint">A face is a resource defined by all its connections. Enter a URL to see its face.</div> 827 <div id="page-content"></div> 828 </main> 829 <script src="/app.js"></script> 830</body> 831</html>`;