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