this repo has no description
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>Tranquil</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=JetBrains+Mono:wght@400;500;600;700;800&display=swap" rel="stylesheet">
10 <style>
11 * { margin: 0; padding: 0; box-sizing: border-box; }
12
13 body {
14 font-family: 'JetBrains Mono', monospace;
15 line-height: 1.7;
16 background: #2c00ff;
17 color: #ffffff;
18 min-height: 100vh;
19 position: relative;
20 }
21
22 .pattern-container {
23 position: fixed;
24 top: -32px;
25 left: -32px;
26 right: -32px;
27 bottom: -32px;
28 pointer-events: none;
29 z-index: 1;
30 overflow: hidden;
31 }
32
33 .pattern {
34 position: absolute;
35 top: 0;
36 left: 0;
37 width: calc(100% + 500px);
38 height: 100%;
39 animation: drift 80s linear infinite;
40 }
41
42 .dot {
43 position: absolute;
44 width: 10px;
45 height: 10px;
46 background: rgba(255,255,255,0.15);
47 border-radius: 50%;
48 transition: transform 0.04s linear;
49 }
50
51 .pattern-fade {
52 position: fixed;
53 top: 0;
54 left: 0;
55 right: 0;
56 bottom: 0;
57 background: linear-gradient(135deg, transparent 50%, #2c00ff 75%);
58 pointer-events: none;
59 z-index: 2;
60 }
61
62 @keyframes drift {
63 0% { transform: translateX(-500px); }
64 100% { transform: translateX(0); }
65 }
66
67 nav { z-index: 100; }
68 main { position: relative; z-index: 10; }
69 .site-footer { position: relative; z-index: 10; }
70
71 a { color: #ff2400; text-decoration: none; }
72 a:hover { color: #ff5533; }
73
74 nav {
75 position: fixed;
76 top: 12px;
77 left: 32px;
78 right: 32px;
79 background: #1a00a3;
80 padding: 10px 18px;
81 z-index: 100;
82 border-radius: 8px;
83 border: 1px solid rgba(255, 255, 255, 0.1);
84 display: flex;
85 justify-content: space-between;
86 align-items: center;
87 }
88
89 nav .brand {
90 font-weight: 600;
91 font-size: 1rem;
92 letter-spacing: 0.08em;
93 color: #ffffff;
94 text-transform: uppercase;
95 }
96
97 nav .nav-meta {
98 font-size: 0.85rem;
99 color: rgba(255, 255, 255, 0.7);
100 letter-spacing: 0.05em;
101 }
102
103 main {
104 max-width: 1000px;
105 margin: 0 auto;
106 padding: 80px 32px 80px;
107 }
108
109 .meta {
110 display: flex;
111 align-items: center;
112 gap: 16px;
113 margin-bottom: 32px;
114 font-size: 0.8rem;
115 font-weight: 500;
116 text-transform: uppercase;
117 letter-spacing: 0.1em;
118 }
119
120 .category {
121 color: #ff2400;
122 background: rgba(255, 255, 255, 0.95);
123 padding: 4px 10px;
124 border-radius: 4px;
125 }
126
127 .read-time {
128 color: rgba(255, 255, 255, 0.8);
129 }
130
131 h1 {
132 font-size: 2.75rem;
133 font-weight: 600;
134 line-height: 1.15;
135 color: #ffffff;
136 margin-bottom: 32px;
137 letter-spacing: -0.02em;
138 }
139
140 .byline {
141 display: flex;
142 align-items: center;
143 gap: 16px;
144 padding: 24px 0;
145 border-top: 1px solid rgba(255, 255, 255, 0.12);
146 border-bottom: 1px solid rgba(255, 255, 255, 0.12);
147 margin-bottom: 48px;
148 }
149
150 .avatar {
151 width: 44px;
152 height: 44px;
153 border-radius: 50%;
154 background: linear-gradient(135deg, #ff2400 0%, #ff6b4a 100%);
155 }
156
157 .author-info {
158 flex: 1;
159 }
160
161 .author {
162 display: block;
163 font-weight: 500;
164 color: #ffffff;
165 font-size: 1rem;
166 }
167
168 .author-handle {
169 display: block;
170 font-size: 0.85rem;
171 color: rgba(255, 255, 255, 0.8);
172 margin-top: 2px;
173 }
174
175 .verification {
176 font-size: 0.75rem;
177 font-weight: 500;
178 color: rgba(255, 255, 255, 0.85);
179 text-transform: uppercase;
180 letter-spacing: 0.08em;
181 }
182
183 .placeholder-image {
184 aspect-ratio: 16 / 9;
185 background: rgba(255, 255, 255, 0.08);
186 border-radius: 8px;
187 display: flex;
188 align-items: center;
189 justify-content: center;
190 font-size: 0.9rem;
191 color: rgba(255, 255, 255, 0.6);
192 text-transform: uppercase;
193 letter-spacing: 0.1em;
194 border: 1px solid rgba(255, 255, 255, 0.15);
195 }
196
197 figcaption {
198 margin-top: 12px;
199 font-size: 0.85rem;
200 color: rgba(255, 255, 255, 0.75);
201 text-align: center;
202 }
203
204 .carousel {
205 margin: 64px 0 0;
206 }
207
208 .carousel-header {
209 display: flex;
210 justify-content: space-between;
211 align-items: center;
212 margin-bottom: 20px;
213 }
214
215 .carousel-title {
216 font-size: 0.85rem;
217 font-weight: 600;
218 text-transform: uppercase;
219 letter-spacing: 0.1em;
220 color: #ffffff;
221 }
222
223 .carousel-nav {
224 display: flex;
225 gap: 8px;
226 }
227
228 .carousel-nav button {
229 font-family: 'JetBrains Mono', monospace;
230 width: 36px;
231 height: 36px;
232 background: rgba(255, 255, 255, 0.08);
233 border: 1px solid rgba(255, 255, 255, 0.15);
234 border-radius: 6px;
235 color: #ffffff;
236 cursor: pointer;
237 transition: all 0.15s ease;
238 font-size: 1rem;
239 }
240
241 .carousel-nav button:hover {
242 background: rgba(255, 36, 0, 0.15);
243 border-color: #ff2400;
244 }
245
246 .carousel-track {
247 display: flex;
248 gap: 16px;
249 overflow-x: auto;
250 scroll-snap-type: x mandatory;
251 scrollbar-width: none;
252 -ms-overflow-style: none;
253 padding-bottom: 8px;
254 -webkit-overflow-scrolling: touch;
255 user-select: none;
256 }
257
258 .carousel-track::-webkit-scrollbar {
259 display: none;
260 }
261
262 .carousel-slide {
263 flex: 0 0 70%;
264 scroll-snap-align: start;
265 }
266
267 .carousel-slide .placeholder-image {
268 aspect-ratio: 16 / 10;
269 }
270
271 .carousel-label {
272 margin-top: 12px;
273 font-size: 0.8rem;
274 font-weight: 500;
275 color: rgba(255, 255, 255, 0.85);
276 text-transform: uppercase;
277 letter-spacing: 0.08em;
278 }
279
280 .content {
281 font-size: 1.05rem;
282 font-weight: 400;
283 }
284
285 .content p {
286 margin-bottom: 28px;
287 }
288
289 .lede {
290 font-size: 1.3rem;
291 font-weight: 500;
292 color: #ffffff;
293 line-height: 1.5;
294 }
295
296 .content h2 {
297 font-size: 0.9rem;
298 font-weight: 600;
299 text-transform: uppercase;
300 letter-spacing: 0.1em;
301 color: #ffffff;
302 margin: 56px 0 24px;
303 }
304
305 blockquote {
306 margin: 40px 0;
307 padding: 32px;
308 background: rgba(255, 255, 255, 0.05);
309 border-left: 2px solid #ff2400;
310 border-radius: 0 8px 8px 0;
311 }
312
313 blockquote p {
314 font-size: 1.15rem;
315 color: #ffffff;
316 font-style: italic;
317 margin-bottom: 16px !important;
318 }
319
320 blockquote cite {
321 font-size: 0.8rem;
322 color: rgba(255, 255, 255, 0.8);
323 font-style: normal;
324 text-transform: uppercase;
325 letter-spacing: 0.05em;
326 }
327
328 .context-panel {
329 margin: 40px 0;
330 padding: 24px;
331 background: rgba(255, 255, 255, 0.05);
332 border-radius: 8px;
333 border: 1px solid rgba(255, 255, 255, 0.1);
334 }
335
336 .context-panel h3 {
337 font-size: 0.8rem;
338 font-weight: 600;
339 text-transform: uppercase;
340 letter-spacing: 0.1em;
341 color: #ffffff;
342 margin-bottom: 16px;
343 }
344
345 .context-panel ul {
346 list-style: none;
347 }
348
349 .context-panel li {
350 padding: 10px 0;
351 border-bottom: 1px solid rgba(255, 255, 255, 0.1);
352 }
353
354 .context-panel li:last-child {
355 border-bottom: none;
356 }
357
358 .context-panel a {
359 font-size: 0.95rem;
360 font-weight: 500;
361 color: #ff2400;
362 text-decoration: none;
363 transition: color 0.15s ease;
364 }
365
366 .context-panel a:hover {
367 color: #ff5533;
368 }
369
370 .article-footer {
371 margin-top: 64px;
372 padding-top: 32px;
373 border-top: 1px solid rgba(255, 255, 255, 0.12);
374 }
375
376 .actions {
377 display: flex;
378 gap: 12px;
379 margin-bottom: 24px;
380 }
381
382 .actions button {
383 font-family: 'JetBrains Mono', monospace;
384 font-size: 0.85rem;
385 font-weight: 500;
386 text-transform: uppercase;
387 letter-spacing: 0.06em;
388 padding: 14px 24px;
389 background: rgba(255, 255, 255, 0.06);
390 border: 1px solid rgba(255, 255, 255, 0.12);
391 border-radius: 6px;
392 color: #ffffff;
393 cursor: pointer;
394 transition: all 0.15s ease;
395 }
396
397 .actions button:hover {
398 background: rgba(255, 36, 0, 0.15);
399 border-color: #ff2400;
400 color: #ffffff;
401 }
402
403 .attestation-info {
404 display: flex;
405 flex-wrap: wrap;
406 gap: 24px;
407 font-size: 0.8rem;
408 color: rgba(255, 255, 255, 0.7);
409 text-transform: uppercase;
410 letter-spacing: 0.05em;
411 }
412
413 .site-footer {
414 max-width: 1000px;
415 margin: 0 auto;
416 padding: 48px 32px;
417 display: flex;
418 justify-content: space-between;
419 font-size: 0.8rem;
420 color: rgba(255, 255, 255, 0.65);
421 text-transform: uppercase;
422 letter-spacing: 0.05em;
423 border-top: 1px solid rgba(255, 255, 255, 0.12);
424 }
425
426 ::selection {
427 background: rgba(255, 36, 0, 0.4);
428 }
429 </style>
430</head>
431<body>
432
433<div class="pattern-container">
434 <div class="pattern"></div>
435</div>
436<div class="pattern-fade"></div>
437
438<nav>
439 <span class="brand">Tranquil</span>
440 <span class="nav-meta">0.1.0</span>
441</nav>
442
443<main>
444 <article>
445 <div class="meta">
446 <span class="category">Landing page</span>
447 <span class="read-time">1 min read</span>
448 </div>
449
450 <h1>Lorem Ipsum Dolor Sit Amet Consectetur</h1>
451
452 <div class="byline">
453 <div class="avatar"></div>
454 <div class="author-info">
455 <span class="author">Mysterious benefactor</span>
456 <span class="author-handle">@lewis.moe</span>
457 </div>
458 <div class="verification">47 attestations</div>
459 </div>
460
461 <div class="content">
462 <blockquote>
463 <p>"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."</p>
464 <cite>Cicero, De Finibus Bonorum et Malorum</cite>
465 </blockquote>
466
467 <p class="lede">Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit.</p>
468
469 <p>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.</p>
470
471 <p>Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt.</p>
472
473 <h2>Neque Porro Quisquam</h2>
474
475 <p>Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.</p>
476
477 <p>Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur.</p>
478
479 <h2>Quis Autem Vel Eum</h2>
480
481 <p>Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur.</p>
482
483 <p>At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident.</p>
484
485 <p>Similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio.</p>
486
487 <p>Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus.</p>
488
489 <p>Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae.</p>
490
491 <div class="carousel">
492 <div class="carousel-header">
493 <span class="carousel-title">Interface</span>
494 <div class="carousel-nav">
495 <button class="carousel-prev">←</button>
496 <button class="carousel-next">→</button>
497 </div>
498 </div>
499 <div class="carousel-track">
500 <div class="carousel-slide">
501 <div class="placeholder-image">Dashboard goes here</div>
502 <div class="carousel-label">Dashboard</div>
503 </div>
504 <div class="carousel-slide">
505 <div class="placeholder-image">Profile Settings go here</div>
506 <div class="carousel-label">Profile Settings</div>
507 </div>
508 <div class="carousel-slide">
509 <div class="placeholder-image">Account Security goes here</div>
510 <div class="carousel-label">Account Security</div>
511 </div>
512 <div class="carousel-slide">
513 <div class="placeholder-image">Repository Browser goes here</div>
514 <div class="carousel-label">Repository Browser</div>
515 </div>
516 <div class="carousel-slide">
517 <div class="placeholder-image">OAuth Applications go here</div>
518 <div class="carousel-label">OAuth Applications</div>
519 </div>
520 <div class="carousel-slide">
521 <div class="placeholder-image">Invite Codes go here</div>
522 <div class="carousel-label">Invite Codes</div>
523 </div>
524 </div>
525 </div>
526 </div>
527
528 <footer class="article-footer">
529 <div class="actions">
530 <button>Propagate</button>
531 <button>Annotate</button>
532 <button>Verify Source</button>
533 </div>
534
535 <div class="attestation-info">
536 <span>hash: 7f3a9c...</span>
537 <span>signed: 2847.12.03</span>
538 <span>nodes: 12,847</span>
539 </div>
540 </footer>
541 </article>
542</main>
543
544<footer class="site-footer">
545 <div>Mesh Commons License</div>
546 <div>node: local-7f3a</div>
547</footer>
548
549<script>
550const pattern = document.querySelector('.pattern');
551const spacing = 32;
552const cols = Math.ceil((window.innerWidth + 600) / spacing);
553const rows = Math.ceil((window.innerHeight + 100) / spacing);
554const dots = [];
555
556for (let y = 0; y < rows; y++) {
557 for (let x = 0; x < cols; x++) {
558 const dot = document.createElement('div');
559 dot.className = 'dot';
560 dot.style.left = (x * spacing) + 'px';
561 dot.style.top = (y * spacing) + 'px';
562 pattern.appendChild(dot);
563 dots.push({ el: dot, x: x * spacing, y: y * spacing });
564 }
565}
566
567let mouseX = -1000, mouseY = -1000;
568document.addEventListener('mousemove', e => {
569 mouseX = e.clientX;
570 mouseY = e.clientY;
571});
572
573function updateDots() {
574 const patternRect = pattern.getBoundingClientRect();
575 dots.forEach(dot => {
576 const dotX = patternRect.left + dot.x + 5;
577 const dotY = patternRect.top + dot.y + 5;
578 const dist = Math.hypot(mouseX - dotX, mouseY - dotY);
579 const maxDist = 120;
580 const scale = Math.min(1, Math.max(0.1, dist / maxDist));
581 dot.el.style.transform = `scale(${scale})`;
582 });
583 requestAnimationFrame(updateDots);
584}
585updateDots();
586
587const track = document.querySelector('.carousel-track');
588const prevBtn = document.querySelector('.carousel-prev');
589const nextBtn = document.querySelector('.carousel-next');
590const slideWidth = track?.querySelector('.carousel-slide')?.offsetWidth + 16;
591
592prevBtn?.addEventListener('click', () => {
593 track.scrollBy({ left: -slideWidth, behavior: 'smooth' });
594});
595nextBtn?.addEventListener('click', () => {
596 track.scrollBy({ left: slideWidth, behavior: 'smooth' });
597});
598
599let isDragging = false;
600let startX, scrollLeft;
601
602track?.addEventListener('mousedown', e => {
603 isDragging = true;
604 track.style.cursor = 'grabbing';
605 track.style.scrollSnapType = 'none';
606 startX = e.pageX - track.offsetLeft;
607 scrollLeft = track.scrollLeft;
608});
609
610track?.addEventListener('mouseleave', () => {
611 isDragging = false;
612 track.style.cursor = 'grab';
613 track.style.scrollSnapType = 'x mandatory';
614});
615
616function snapTo(target, duration = 120) {
617 const start = track.scrollLeft;
618 const distance = target - start;
619 const startTime = performance.now();
620 function step(currentTime) {
621 const elapsed = currentTime - startTime;
622 const progress = Math.min(elapsed / duration, 1);
623 const ease = 1 - Math.pow(1 - progress, 3);
624 track.scrollLeft = start + distance * ease;
625 if (progress < 1) requestAnimationFrame(step);
626 else track.style.scrollSnapType = 'x mandatory';
627 }
628 requestAnimationFrame(step);
629}
630
631track?.addEventListener('mouseup', () => {
632 isDragging = false;
633 track.style.cursor = 'grab';
634 const slideW = track.querySelector('.carousel-slide').offsetWidth + 16;
635 const targetIndex = Math.round(track.scrollLeft / slideW);
636 snapTo(targetIndex * slideW);
637});
638
639track?.addEventListener('mousemove', e => {
640 if (!isDragging) return;
641 e.preventDefault();
642 const x = e.pageX - track.offsetLeft;
643 const walk = (x - startX) * 1.5;
644 track.scrollLeft = scrollLeft - walk;
645});
646
647if (track) track.style.cursor = 'grab';
648</script>
649</body>
650</html>