This repository has no description
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>`;