pushes on tangled sites.wisp.place/zzstoatzz.io/punch
fun tangled
7
fork

Configure Feed

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

at main 744 lines 17 kB view raw
1/* punch — late-80s arcade high-score board, mobile first. */ 2 3@import url("https://fonts.googleapis.com/css2?family=Press+Start+2P&family=Silkscreen:wght@400;700&family=VT323&display=swap"); 4 5:root, 6[data-theme="dark"] { 7 --bg: #1a1028; 8 --bg-deep: #0f0820; 9 --surface: #2a1b3d; 10 --surface-hi: #3d2952; 11 --border: #4a3366; 12 --border-hi: #6b4a8a; 13 14 --text: #f2e6d0; 15 --text-dim: #9a8cb0; 16 --text-fade: #62557a; 17 18 --accent: #ff6d9c; 19 --accent-alt: #5be5c5; 20 --accent-warm: #ffb347; 21 22 --rank-1: #ffd13e; 23 --rank-2: #d4d4d4; 24 --rank-3: #e08a54; 25 26 --btn-bg: #2a1b3d; 27 --btn-shadow: #0f0820; 28 29 --scan-opacity: 0.09; 30 --grain-opacity: 0.38; 31 --phosphor-opacity: 0.06; 32} 33 34[data-theme="light"] { 35 --bg: #f2e4c4; 36 --bg-deep: #e0cc9c; 37 --surface: #fff5d6; 38 --surface-hi: #ffeab0; 39 --border: #a88856; 40 --border-hi: #7a5e2c; 41 42 --text: #2a1808; 43 --text-dim: #5a4226; 44 --text-fade: #8a7450; 45 46 --accent: #c63b5a; 47 --accent-alt: #2a7a6a; 48 --accent-warm: #c97030; 49 50 --rank-1: #c89030; 51 --rank-2: #7c7c7c; 52 --rank-3: #a5562e; 53 54 --btn-bg: #fff5d6; 55 --btn-shadow: #7a5e2c; 56 57 --scan-opacity: 0.05; 58 --grain-opacity: 0.18; 59 --phosphor-opacity: 0.04; 60} 61 62@media (prefers-color-scheme: light) { 63 [data-theme="auto"] { 64 --bg: #f2e4c4; 65 --bg-deep: #e0cc9c; 66 --surface: #fff5d6; 67 --surface-hi: #ffeab0; 68 --border: #a88856; 69 --border-hi: #7a5e2c; 70 --text: #2a1808; 71 --text-dim: #5a4226; 72 --text-fade: #8a7450; 73 --accent: #c63b5a; 74 --accent-alt: #2a7a6a; 75 --accent-warm: #c97030; 76 --rank-1: #c89030; 77 --rank-2: #7c7c7c; 78 --rank-3: #a5562e; 79 --btn-bg: #fff5d6; 80 --btn-shadow: #7a5e2c; 81 } 82} 83 84* { 85 box-sizing: border-box; 86 /* keep pixel fonts crunchy — no AA */ 87 -webkit-font-smoothing: none; 88 -moz-osx-font-smoothing: grayscale; 89 font-smooth: never; 90 image-rendering: pixelated; 91 image-rendering: crisp-edges; 92} 93 94html, body { 95 margin: 0; 96 padding: 0; 97 background: var(--bg); 98 color: var(--text); 99 font-family: "Silkscreen", ui-monospace, monospace; 100 font-size: 11px; 101 letter-spacing: 0.04em; 102 line-height: 1.55; 103 overflow-x: hidden; 104 -webkit-text-size-adjust: 100%; 105} 106 107body { 108 background: 109 radial-gradient(ellipse at top, var(--surface) 0%, var(--bg) 45%, var(--bg-deep) 100%); 110 background-attachment: fixed; 111 min-height: 100dvh; 112} 113 114/* ---- CRT stack: scanlines + grain — layered, not one-shot ---- */ 115 116.scanlines { 117 position: fixed; 118 inset: 0; 119 pointer-events: none; 120 z-index: 100; 121} 122 123/* scanlines — horizontal CRT stripes at a tight 2px/1px period + vertical 124 phosphor stripes mimicking a shadow-mask TV. */ 125.scanlines::before { 126 content: ""; 127 position: absolute; 128 inset: 0; 129 background: 130 repeating-linear-gradient( 131 to bottom, 132 transparent 0, 133 transparent 2px, 134 rgba(0, 0, 0, var(--scan-opacity)) 2px, 135 rgba(0, 0, 0, var(--scan-opacity)) 3px 136 ), 137 repeating-linear-gradient( 138 to right, 139 rgba(255, 70, 120, var(--phosphor-opacity)) 0 1px, 140 rgba(90, 230, 200, var(--phosphor-opacity)) 1px 2px, 141 rgba(100, 140, 255, var(--phosphor-opacity)) 2px 3px 142 ); 143 mix-blend-mode: multiply; 144} 145 146/* SVG dither/grain — baked data URI so wisp's rewriter can't touch it */ 147.scanlines::after { 148 content: ""; 149 position: absolute; 150 inset: 0; 151 opacity: var(--grain-opacity); 152 mix-blend-mode: overlay; 153 background-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='3.2' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.4 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); 154 background-size: 120px 120px; 155 image-rendering: pixelated; 156} 157 158.cabinet { 159 max-width: 720px; 160 margin: 0 auto; 161 padding: 16px 14px 48px; 162 display: flex; 163 flex-direction: column; 164 gap: 18px; 165} 166 167/* ---- marquee ---- */ 168 169.marquee { 170 display: flex; 171 flex-direction: column; 172 gap: 8px; 173} 174 175.marquee-row { 176 display: flex; 177 align-items: flex-start; 178 justify-content: space-between; 179 gap: 12px; 180} 181 182h1.display { 183 font-family: "Press Start 2P", monospace; 184 font-size: clamp(24px, 7vw, 48px); 185 font-weight: 400; 186 letter-spacing: 0.02em; 187 line-height: 1; 188 margin: 0; 189 color: var(--text); 190 /* chromatic fringe + hard pixel dropshadow + CRT bloom */ 191 text-shadow: 192 3px 0 0 var(--accent), 193 -3px 0 0 var(--accent-alt), 194 0 4px 0 var(--btn-shadow), 195 0 4px 0 var(--btn-shadow), 196 0 0 16px color-mix(in srgb, var(--accent) 30%, transparent); 197} 198 199.toolbar { 200 display: flex; 201 gap: 8px; 202 flex-shrink: 0; 203 padding-top: 6px; 204} 205 206.tagline { 207 font-family: "Silkscreen", monospace; 208 font-size: 10px; 209 font-weight: 400; 210 margin: 0; 211 color: var(--text-dim); 212 letter-spacing: 0.02em; 213 line-height: 1.5; 214} 215 216.tagline code { 217 font-family: "Silkscreen", monospace; 218 font-size: 9px; 219 letter-spacing: 0; 220 padding: 1px 4px; 221 background: var(--surface); 222 color: var(--text); 223 border: 1px solid var(--border); 224} 225 226.credits { 227 font-family: "Silkscreen", monospace; 228 font-size: 9px; 229 letter-spacing: 0.05em; 230 text-transform: uppercase; 231 margin: 6px 0 0; 232 display: flex; 233 flex-wrap: wrap; 234 align-items: center; 235 gap: 8px; 236 row-gap: 6px; 237 color: var(--text-fade); 238} 239 240.credits a { 241 color: var(--accent); 242 text-decoration: none; 243 border-bottom: 1px dotted var(--accent); 244} 245 246.credits a:hover { 247 color: var(--text); 248 border-bottom-color: var(--text); 249} 250 251.credits .sep { 252 color: var(--text-fade); 253} 254 255.blink { 256 color: var(--accent); 257 animation: blink 1.1s steps(2, jump-none) infinite; 258} 259 260@keyframes blink { 261 50% { opacity: 0.15; } 262} 263 264/* ---- stats strip ---- */ 265 266.stats { 267 display: flex; 268 flex-direction: column; 269 gap: 8px; 270 padding: 12px 14px; 271 background: var(--surface); 272 border: 3px solid var(--border); 273 border-radius: 0; 274 /* thicker pixel 3D bevel */ 275 box-shadow: 276 6px 6px 0 var(--btn-shadow), 277 inset 3px 3px 0 var(--border-hi), 278 inset -3px -3px 0 var(--bg-deep); 279 font-family: "Silkscreen", monospace; 280 font-size: 10px; 281 text-transform: uppercase; 282} 283 284.stats-row { 285 display: flex; 286 align-items: baseline; 287 flex-wrap: wrap; 288 gap: 8px; 289} 290 291.stats-meta { 292 padding-top: 8px; 293 border-top: 1px dashed var(--border-hi); 294 font-size: 9px; 295 letter-spacing: 0.08em; 296 color: var(--text-dim); 297 gap: 6px; 298} 299 300.hud-label { 301 color: var(--text-fade); 302} 303 304.hud-time { 305 color: var(--accent-alt); 306 font-weight: 700; 307 letter-spacing: 0.1em; 308 text-shadow: 0 0 6px color-mix(in srgb, var(--accent-alt) 50%, transparent); 309} 310 311.hud-cursor { 312 color: var(--accent-alt); 313 margin-left: 2px; 314} 315 316.stat-val { 317 font-family: "Silkscreen", monospace; 318 font-weight: 700; 319 font-size: 13px; 320 color: var(--accent-warm); 321 font-variant-numeric: tabular-nums; 322 margin-right: 6px; 323 letter-spacing: 0.04em; 324 text-shadow: 1px 1px 0 var(--btn-shadow); 325} 326 327.stat-lbl { 328 color: var(--text-dim); 329 letter-spacing: 0.08em; 330} 331 332.sep { 333 color: var(--text-fade); 334} 335 336/* ---- status ---- */ 337 338.status { 339 padding: 10px 12px; 340 background: var(--surface); 341 border: 2px dashed var(--border-hi); 342 box-shadow: inset 2px 2px 0 var(--bg-deep); 343 font-family: "Silkscreen", monospace; 344 font-size: 10px; 345 color: var(--text-dim); 346 text-transform: uppercase; 347 letter-spacing: 0.04em; 348 display: flex; 349 align-items: center; 350 gap: 10px; 351} 352 353/* our display: flex above overrides the UA [hidden] { display: none }, so 354 restore it explicitly here. */ 355.status[hidden] { display: none; } 356 357.status::before { 358 content: "●"; 359 color: var(--accent-alt); 360 animation: blink 1.4s steps(2, jump-none) infinite; 361 font-size: 10px; 362} 363 364/* ---- buttons ---- */ 365 366.btn { 367 font-family: "Silkscreen", monospace; 368 font-size: 10px; 369 text-transform: uppercase; 370 letter-spacing: 0.08em; 371 padding: 8px 12px; 372 background: var(--btn-bg); 373 color: var(--text); 374 border: 3px solid var(--border-hi); 375 border-radius: 0; 376 cursor: pointer; 377 text-decoration: none; 378 display: inline-flex; 379 align-items: center; 380 justify-content: center; 381 gap: 6px; 382 /* 3D cabinet button */ 383 box-shadow: 384 5px 5px 0 var(--btn-shadow), 385 inset 3px 3px 0 color-mix(in srgb, var(--surface-hi) 70%, transparent), 386 inset -3px -3px 0 color-mix(in srgb, var(--bg-deep) 70%, transparent); 387 transition: transform 0.08s, box-shadow 0.08s; 388 line-height: 1; 389 user-select: none; 390} 391 392.btn:hover { 393 color: var(--accent); 394 border-color: var(--accent); 395} 396 397.btn:active { 398 transform: translate(3px, 3px); 399 box-shadow: 400 1px 1px 0 var(--btn-shadow), 401 inset 2px 2px 0 color-mix(in srgb, var(--bg-deep) 60%, transparent), 402 inset -2px -2px 0 color-mix(in srgb, var(--surface-hi) 60%, transparent); 403} 404 405.btn-icon { 406 width: 36px; 407 height: 36px; 408 padding: 0; 409 font-size: 16px; 410} 411 412.btn-icon svg { 413 display: block; 414} 415 416/* ---- search ---- */ 417 418.search input { 419 width: 100%; 420 padding: 12px 14px; 421 background: var(--surface); 422 color: var(--text); 423 border: 3px solid var(--border); 424 border-radius: 0; 425 /* inverted pixel 3D — input feels pressed in */ 426 box-shadow: 427 inset 4px 4px 0 var(--bg-deep), 428 inset -3px -3px 0 var(--surface-hi); 429 font-family: "Silkscreen", monospace; 430 /* 16px prevents iOS Safari auto-zooming on focus; anything smaller triggers it. */ 431 font-size: 16px; 432 text-transform: uppercase; 433 letter-spacing: 0.08em; 434 min-height: 44px; 435} 436 437.search input::placeholder { 438 color: var(--text-fade); 439 font-family: "Silkscreen", monospace; 440 font-size: 16px; 441 letter-spacing: 0.08em; 442} 443 444.search input:focus { 445 outline: none; 446 border-color: var(--accent); 447} 448 449/* ---- board ---- */ 450 451.board { 452 list-style: none; 453 margin: 0; 454 padding: 0; 455 display: flex; 456 flex-direction: column; 457 gap: 6px; 458} 459 460.row { 461 background: var(--surface); 462 border: 3px solid var(--border); 463 border-radius: 0; 464 box-shadow: 465 5px 5px 0 var(--btn-shadow), 466 inset 3px 3px 0 color-mix(in srgb, var(--surface-hi) 65%, transparent), 467 inset -3px -3px 0 color-mix(in srgb, var(--bg-deep) 65%, transparent); 468 transition: transform 0.08s, box-shadow 0.08s, background 0.08s; 469} 470 471.row-link { 472 display: grid; 473 grid-template-columns: 48px 1fr auto; 474 align-items: center; 475 gap: 10px; 476 padding: 10px 12px; 477 text-decoration: none; 478 color: inherit; 479} 480 481.row:hover { 482 background: var(--surface-hi); 483 border-color: var(--border-hi); 484 transform: translate(-1px, -1px); 485 box-shadow: 486 6px 6px 0 var(--btn-shadow), 487 inset 3px 3px 0 color-mix(in srgb, var(--surface-hi) 65%, transparent), 488 inset -3px -3px 0 color-mix(in srgb, var(--bg-deep) 65%, transparent); 489} 490 491.row:hover .handle { color: var(--accent); } 492.row:active { transform: translate(1px, 1px); } 493 494.row:nth-child(1) { 495 border-color: var(--rank-1); 496 box-shadow: 497 5px 5px 0 var(--rank-1), 498 inset 3px 3px 0 color-mix(in srgb, var(--rank-1) 35%, transparent), 499 inset -3px -3px 0 var(--bg-deep); 500} 501.row:nth-child(2) { 502 border-color: var(--rank-2); 503 box-shadow: 504 5px 5px 0 var(--rank-2), 505 inset 3px 3px 0 color-mix(in srgb, var(--rank-2) 35%, transparent), 506 inset -3px -3px 0 var(--bg-deep); 507} 508.row:nth-child(3) { 509 border-color: var(--rank-3); 510 box-shadow: 511 5px 5px 0 var(--rank-3), 512 inset 3px 3px 0 color-mix(in srgb, var(--rank-3) 35%, transparent), 513 inset -3px -3px 0 var(--bg-deep); 514} 515 516.rank { 517 font-family: "Silkscreen", monospace; 518 font-weight: 700; 519 font-size: 14px; 520 text-align: center; 521 color: var(--text-fade); 522 line-height: 1; 523 letter-spacing: 0.04em; 524 font-variant-numeric: tabular-nums; 525 text-shadow: 1px 1px 0 var(--btn-shadow); 526} 527 528.row:nth-child(1) .rank { color: var(--rank-1); } 529.row:nth-child(2) .rank { color: var(--rank-2); } 530.row:nth-child(3) .rank { color: var(--rank-3); } 531 532.who { 533 display: flex; 534 align-items: center; 535 gap: 10px; 536 min-width: 0; 537} 538 539.avatar { 540 width: 28px; 541 height: 28px; 542 border-radius: 0; 543 background: var(--bg-deep); 544 border: 2px solid var(--border); 545 flex-shrink: 0; 546 background-size: cover; 547 background-position: center; 548 box-shadow: 549 inset 1px 1px 0 color-mix(in srgb, var(--surface-hi) 50%, transparent), 550 inset -1px -1px 0 color-mix(in srgb, var(--bg-deep) 70%, transparent); 551 image-rendering: pixelated; 552 image-rendering: crisp-edges; 553} 554 555.handle { 556 font-family: "Silkscreen", monospace; 557 font-size: 11px; 558 text-transform: uppercase; 559 letter-spacing: 0.04em; 560 color: var(--text); 561 overflow: hidden; 562 text-overflow: ellipsis; 563 white-space: nowrap; 564 transition: color 0.08s; 565} 566 567.count { 568 font-family: "Silkscreen", monospace; 569 font-weight: 700; 570 font-size: 13px; 571 color: var(--accent-warm); 572 font-variant-numeric: tabular-nums; 573 letter-spacing: 0.06em; 574 line-height: 1; 575 white-space: nowrap; 576 text-shadow: 1px 1px 0 var(--btn-shadow); 577} 578 579.count .unit { 580 font-family: "Silkscreen", monospace; 581 font-size: 9px; 582 color: var(--text-fade); 583 margin-left: 5px; 584 text-transform: uppercase; 585 letter-spacing: 0.08em; 586} 587 588/* ---- footer ---- */ 589 590footer { 591 margin-top: 12px; 592 display: flex; 593 flex-direction: column; 594 gap: 8px; 595 font-family: "Silkscreen", monospace; 596 font-size: 9px; 597 color: var(--text-fade); 598 text-transform: uppercase; 599 letter-spacing: 0.05em; 600 line-height: 1.6; 601} 602 603footer p.fine { 604 margin: 0; 605} 606 607footer code { 608 font-family: "Silkscreen", monospace; 609 color: var(--text-dim); 610 text-transform: none; 611 letter-spacing: 0; 612 font-size: 9px; 613 padding: 1px 4px; 614 background: var(--surface); 615 border: 1px solid var(--border); 616} 617 618footer a { 619 color: var(--accent); 620 text-decoration: none; 621 border-bottom: 1px dotted var(--accent); 622} 623 624footer a:hover { 625 color: var(--text); 626 border-bottom-color: var(--text); 627} 628 629footer .links { 630 display: flex; 631 flex-wrap: wrap; 632 align-items: center; 633 gap: 8px; 634 row-gap: 6px; 635} 636 637footer .links .sep { 638 color: var(--text-fade); 639} 640 641/* arcade stack plaques — one per service we actually run on */ 642.built-with { 643 align-items: center; 644 row-gap: 8px; 645} 646 647.built-lbl { 648 color: var(--text-fade); 649 letter-spacing: 0.08em; 650} 651 652.stack-badge { 653 padding: 4px 7px 3px; 654 background: var(--surface); 655 border: 2px solid var(--border-hi); 656 font-family: "Silkscreen", monospace; 657 font-size: 9px; 658 letter-spacing: 0.04em; 659 text-transform: lowercase; 660 text-decoration: none !important; 661 border-bottom: none !important; 662 white-space: nowrap; /* keep the domain intact — never break inside */ 663 flex: 0 0 auto; /* badge stays its natural width; parent wraps it to next line */ 664 box-shadow: 665 3px 3px 0 var(--btn-shadow), 666 inset 2px 2px 0 color-mix(in srgb, var(--surface-hi) 60%, transparent), 667 inset -2px -2px 0 color-mix(in srgb, var(--bg-deep) 60%, transparent); 668 transition: transform 0.08s, box-shadow 0.08s; 669 line-height: 1; 670} 671 672/* keep all three badges on one line on mobile. two moves: 673 - drop the "built with" label (the badges themselves say what's in play) 674 - shrink badge font so the three fit across ~320-430px viewports. */ 675@media (max-width: 520px) { 676 .built-lbl { display: none; } 677 .stack-badge { 678 font-size: 7px; 679 padding: 3px 5px 2px; 680 letter-spacing: 0.02em; 681 border-width: 1px; 682 box-shadow: 683 2px 2px 0 var(--btn-shadow), 684 inset 1px 1px 0 color-mix(in srgb, var(--surface-hi) 60%, transparent), 685 inset -1px -1px 0 color-mix(in srgb, var(--bg-deep) 60%, transparent); 686 } 687 .built-with { gap: 5px; flex-wrap: nowrap; } 688} 689 690.stack-badge:hover { 691 transform: translate(-1px, -1px); 692 box-shadow: 693 4px 4px 0 var(--btn-shadow), 694 inset 2px 2px 0 color-mix(in srgb, var(--surface-hi) 60%, transparent), 695 inset -2px -2px 0 color-mix(in srgb, var(--bg-deep) 60%, transparent); 696} 697 698.badge-teal { color: var(--accent-alt); } 699.badge-pink { color: var(--accent); } 700.badge-amber { color: var(--accent-warm); } 701 702.badge-teal:hover { border-color: var(--accent-alt); } 703.badge-pink:hover { border-color: var(--accent); } 704.badge-amber:hover { border-color: var(--accent-warm); } 705 706.empty { 707 padding: 24px; 708 text-align: center; 709 font-family: "Silkscreen", monospace; 710 font-size: 11px; 711 color: var(--text-fade); 712 text-transform: uppercase; 713 letter-spacing: 0.1em; 714} 715 716/* ---- tablet + up ---- */ 717 718@media (min-width: 560px) { 719 body { font-size: 12px; } 720 .cabinet { padding: 28px 22px 64px; gap: 22px; } 721 .row-link { 722 grid-template-columns: 60px 1fr auto; 723 padding: 12px 14px; 724 } 725 .rank { font-size: 16px; } 726 .avatar { width: 32px; height: 32px; } 727 .handle { font-size: 12px; } 728 .count { font-size: 15px; } 729 .count .unit { font-size: 9px; } 730 .btn-icon { width: 40px; height: 40px; font-size: 18px; } 731 .stat-val { font-size: 15px; } 732} 733 734/* ---- desktop ---- */ 735 736@media (min-width: 800px) { 737 .cabinet { padding: 36px 24px 80px; } 738 h1.display { 739 text-shadow: 740 3px 0 0 var(--accent), 741 -3px 0 0 var(--accent-alt), 742 0 4px 0 var(--btn-shadow); 743 } 744}