| … | … | @@ -507,8 +507,8 @@ nav{margin:.4rem 0 1rem;display:flex;gap:1rem;font-size:.9rem} |
| 507 | 507 | details.post>summary{cursor:pointer;color:var(--fg-faint);font-style:italic;list-style:revert} |
| 508 | 508 | .meta{color:var(--fg-faint);font-size:.8rem;margin-top:.35rem}.meta .did{color:var(--fg-faint)} |
| 509 | 509 | .controls{display:flex;gap:.5rem;align-items:center;margin-top:.4rem}.controls select,.controls button{font:inherit;padding:.3rem} |
| 510 | | .badge{display:inline-block;font-size:.7rem;font-weight:600;padding:.05rem .4rem;border-radius:.6rem;margin-left:.4rem;background:#e8f0fe;color:var(--accent)} |
| 511 | | .lbl{display:inline-block;font-size:.7rem;font-weight:600;padding:.05rem .4rem;border-radius:.6rem;margin-left:.4rem;background:#fde8e8;color:#b91c1c} |
| 510 | .badge{display:inline-block;font-size:.7rem;font-weight:600;padding:.05rem .4rem;border-radius:.6rem;margin-left:.4rem;background:var(--badge-bg);color:var(--accent)} |
| 511 | .lbl{display:inline-block;font-size:.7rem;font-weight:600;padding:.05rem .4rem;border-radius:.6rem;margin-left:.4rem;background:var(--danger-bg);color:var(--danger-text)} |
| 512 | 512 | .tag{text-decoration:none}.tag:hover{text-decoration:underline} |
| 513 | 513 | .viewhdr{margin:.6rem 0;font-weight:600}.empty{color:var(--fg-faint);font-style:italic} |
| 514 | 514 | .who{font-size:.85rem;color:var(--fg-faint);margin-left:auto} |
| … | … | @@ -516,8 +516,8 @@ details.post>summary{cursor:pointer;color:var(--fg-faint);font-style:italic;list |
| 516 | 516 | .byline{display:flex;align-items:center;gap:.5rem;text-decoration:none;color:inherit;min-width:0} |
| 517 | 517 | .byline:hover .name{text-decoration:underline} |
| 518 | 518 | .byline .name{font-weight:600;font-size:.95rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap} |
| 519 | | .pfp{width:36px;height:36px;border-radius:50%;object-fit:cover;background:#e5e7eb;flex:none} |
| 520 | | .pfp.none{display:inline-block;background:#e5e7eb} |
| 519 | .pfp{width:36px;height:36px;border-radius:50%;object-fit:cover;background:var(--line);flex:none} |
| 520 | .pfp.none{display:inline-block;background:var(--line)} |
| 521 | 521 | .pfp.big{width:72px;height:72px} |
| 522 | 522 | .meta .permalink{color:var(--fg-faint);text-decoration:none}.meta .permalink:hover{text-decoration:underline} |
| 523 | 523 | .mention{text-decoration:none;font-weight:500}.mention:hover{text-decoration:underline} |
| … | … | @@ -544,13 +544,13 @@ details.post>summary{cursor:pointer;color:var(--fg-faint);font-style:italic;list |
| 544 | 544 | .focus{border-left:3px solid #444;padding-left:.6rem;margin:.4rem 0} |
| 545 | 545 | /* A lens is a NAMED FOREIGN source. Styled visibly apart from our own posts — a reader must never have |
| 546 | 546 | to guess whether a reply is one this node holds or one it is relaying from someone else's AppView. */ |
| 547 | | .lens{margin-top:1rem;border-top:1px dashed #cbd5e1;padding-top:.5rem} |
| 547 | .lens{margin-top:1rem;border-top:1px dashed var(--lens-line);padding-top:.5rem} |
| 548 | 548 | /* The ancestor fill sits ABOVE the focused post, so its rule belongs on the bottom edge — otherwise the |
| 549 | 549 | section reads as separating itself from the post it precedes. */ |
| 550 | | .lensup{margin:.3rem 0 .6rem;border-top:0;border-bottom:1px dashed #cbd5e1;padding:0 0 .4rem} |
| 550 | .lensup{margin:.3rem 0 .6rem;border-top:0;border-bottom:1px dashed var(--lens-line);padding:0 0 .4rem} |
| 551 | 551 | .lens h3{font-size:.85rem;color:var(--fg-dim);font-weight:600;margin:.3rem 0} |
| 552 | | .lensname{color:#3b5bdb} |
| 553 | | .lpost{border-left:2px solid #dbe4ff;padding:.3rem 0 .3rem .7rem;margin:.4rem 0} |
| 552 | .lensname{color:var(--lens)} |
| 553 | .lpost{border-left:2px solid var(--lens-edge);padding:.3rem 0 .3rem .7rem;margin:.4rem 0} |
| 554 | 554 | .lwho{font-size:.9rem;font-weight:600} |
| 555 | 555 | .lhandle{font-weight:400;color:var(--fg-faint)} |
| 556 | 556 | .ltext{white-space:pre-wrap;margin:.15rem 0} |
| … | … | @@ -560,9 +560,9 @@ details.post>summary{cursor:pointer;color:var(--fg-faint);font-style:italic;list |
| 560 | 560 | .delw{display:inline} |
| 561 | 561 | .delw>summary{display:inline;list-style:none;cursor:pointer;color:var(--fg-faint)} |
| 562 | 562 | .delw>summary::-webkit-details-marker{display:none} |
| 563 | | .delw>summary:hover{color:#c92a2a} |
| 563 | .delw>summary:hover{color:var(--danger)} |
| 564 | 564 | .delf{display:inline;margin-left:.3rem} |
| 565 | | .delbtn{font:inherit;font-size:.78rem;border:1px solid #c92a2a;background:#c92a2a;color:#fff;border-radius:999px;padding:.15rem .5rem;cursor:pointer} |
| 565 | .delbtn{font:inherit;font-size:.78rem;border:1px solid var(--danger);background:var(--danger);color:#fff;border-radius:999px;padding:.15rem .5rem;cursor:pointer} |
| 566 | 566 | .delbtn:hover{filter:brightness(1.1)} |
| 567 | 567 | .modrow{display:flex;align-items:center;gap:.6rem;margin-top:.5rem;font-size:.85rem} |
| 568 | 568 | .modf{display:inline} |
| … | … | @@ -571,9 +571,9 @@ details.post>summary{cursor:pointer;color:var(--fg-faint);font-style:italic;list |
| 571 | 571 | .modw{display:inline} |
| 572 | 572 | .modw>summary{display:inline;list-style:none;cursor:pointer;color:var(--fg-faint,#888);text-decoration:underline} |
| 573 | 573 | .modw>summary::-webkit-details-marker{display:none} |
| 574 | | .modw>summary:hover{color:#c92a2a} |
| 575 | | .blockbtn{font:inherit;font-size:.8rem;border:1px solid #c92a2a;background:#c92a2a;color:#fff;border-radius:999px;padding:.2rem .6rem;cursor:pointer;margin-left:.3rem} |
| 576 | | .blockbtn.on{background:none;color:#c92a2a} |
| 574 | .modw>summary:hover{color:var(--danger)} |
| 575 | .blockbtn{font:inherit;font-size:.8rem;border:1px solid var(--danger);background:var(--danger);color:#fff;border-radius:999px;padding:.2rem .6rem;cursor:pointer;margin-left:.3rem} |
| 576 | .blockbtn.on{background:none;color:var(--danger)} |
| 577 | 577 | .navsearch{margin-left:auto} |
| 578 | 578 | .navsearch input{font:inherit;font-size:.85rem;padding:.2rem .5rem;border:1px solid var(--line,#e5e5e5);border-radius:999px;background:var(--bg,#fff);color:inherit;width:8rem} |
| 579 | 579 | .navsearch input:focus{outline:2px solid var(--accent,#1a56db);outline-offset:1px;width:11rem} |
| … | … | @@ -592,7 +592,7 @@ details.post>summary{cursor:pointer;color:var(--fg-faint);font-style:italic;list |
| 592 | 592 | .controls label{display:inline-flex;align-items:center;gap:.3rem;min-width:0;font-size:.85rem;color:var(--fg-dim,#5c6672)} |
| 593 | 593 | /* min-width:0 is the load-bearing half: a flex item defaults to min-width:auto, so a select refuses to |
| 594 | 594 | shrink below its longest option and pushes its siblings out of the box instead of wrapping. */ |
| 595 | | .controls select{min-width:0;max-width:100%;border:1px solid var(--line,#ccc);border-radius:.3rem;background:var(--bg,#fff);color:inherit} |
| 595 | .controls select,.controls button{min-width:0;max-width:100%;border:1px solid var(--line);border-radius:var(--r1);background:var(--bg);color:inherit} |
| 596 | 596 | /* The post button always ends the row, on whatever line it lands on. */ |
| 597 | 597 | #post-btn{margin-left:auto;flex:none} |
| 598 | 598 | .cc{flex:none} |
| … | … | @@ -602,7 +602,7 @@ details.post>summary{cursor:pointer;color:var(--fg-faint);font-style:italic;list |
| 602 | 602 | discovered after posting; strong enough to be seen, quiet enough not to shout on every page. */ |
| 603 | 603 | /* Staleness. Above everything, because it qualifies everything below it — but a notice, not an alarm: |
| 604 | 604 | it is frequently true and correctly ignorable on a P2P node. */ |
| 605 | | .stale{font-size:.82rem;background:var(--bg-soft);border:1px solid var(--line);border-left:3px solid #b8860b;border-radius:var(--r1);padding:.45rem .6rem;margin:0 0 var(--s3)} |
| 605 | .stale{font-size:.82rem;background:var(--bg-soft);border:1px solid var(--line);border-left:3px solid var(--warn);border-radius:var(--r1);padding:.45rem .6rem;margin:0 0 var(--s3)} |
| 606 | 606 | .composerwho{font-size:.8rem;color:var(--fg-faint,#6b7480);margin:0 0 .4rem} |
| 607 | 607 | .composerwho strong{color:var(--fg);font-weight:600} |
| 608 | 608 | @media(max-width:640px){ |
| … | … | @@ -613,7 +613,7 @@ details.post>summary{cursor:pointer;color:var(--fg-faint);font-style:italic;list |
| 613 | 613 | #post-btn{margin-left:0;flex:1 1 100%} |
| 614 | 614 | } |
| 615 | 615 | .reportbtn{font:inherit;font-size:.85rem;border:none;background:none;color:var(--fg-faint,#6b7480);cursor:pointer;padding:.3rem .35rem;margin:-.3rem -.1rem} |
| 616 | | .reportbtn:hover{color:#c92a2a} |
| 616 | .reportbtn:hover{color:var(--danger)} |
| 617 | 617 | .reportbox{display:flex;flex-wrap:wrap;gap:.4rem;align-items:center;margin-top:.4rem;padding:.5rem;border:1px solid var(--line,#e5e5e5);border-radius:var(--r1,.375rem);font-size:.85rem} |
| 618 | 618 | .reportbox select,.reportbox input,.reportbox button{font:inherit;font-size:.85rem;padding:.25rem .4rem} |
| 619 | 619 | .reportbox input{flex:1;min-width:8rem} |
| … | … | @@ -623,14 +623,14 @@ details.post>summary{cursor:pointer;color:var(--fg-faint);font-style:italic;list |
| 623 | 623 | .listrow:hover{background:var(--bg-soft,#f7f8fa)} |
| 624 | 624 | .listname{font-weight:600} |
| 625 | 625 | .listkind{font-size:.75rem;color:var(--fg-faint,#6b7480);border:1px solid var(--line,#e5e5e5);border-radius:999px;padding:.05rem .5rem} |
| 626 | | .listkind.mod{color:#c92a2a;border-color:#c92a2a} |
| 626 | .listkind.mod{color:var(--danger);border-color:var(--danger)} |
| 627 | 627 | .listdesc{font-size:.85rem;color:var(--fg-dim,#5c6672);width:100%} |
| 628 | 628 | .profbanner{margin:0 0 .6rem;border-radius:var(--r2,.625rem);overflow:hidden;background:var(--bg-soft,#f7f8fa)} |
| 629 | 629 | .profbanner img{display:block;width:100%;aspect-ratio:3/1;object-fit:cover} |
| 630 | 630 | .profbanner.small img{aspect-ratio:4/1} |
| 631 | 631 | .bmf{display:inline} |
| 632 | 632 | .bmbtn{font:inherit;font-size:.9rem;line-height:1;border:none;background:none;color:var(--fg-faint);cursor:pointer;padding:.3rem .45rem;margin:-.3rem -.1rem;transition:transform .08s ease,color .12s ease;touch-action:manipulation} |
| 633 | | .bmbtn:hover{color:#f59f00}.bmbtn.on{color:#f59f00} |
| 633 | .bmbtn:hover{color:var(--bookmark)}.bmbtn.on{color:var(--bookmark)} |
| 634 | 634 | .bmbtn:active{transform:scale(.88)} |
| 635 | 635 | .bmbtn:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:.3rem} |
| 636 | 636 | /* a11y. A skip link is the difference between reaching the content and tabbing the whole nav on every |
| … | … | @@ -663,15 +663,15 @@ a:focus-visible,button:focus-visible,input:focus-visible,textarea:focus-visible, |
| 663 | 663 | .qcancel{font-size:.8rem} |
| 664 | 664 | .stath{font-size:.85rem;color:var(--fg-dim);margin:1rem 0 .3rem;text-transform:uppercase;letter-spacing:.03em} |
| 665 | 665 | .statblk{border:1px solid var(--line);border-radius:4px;padding:.5rem .6rem;margin:.4rem 0} |
| 666 | | .statblk.alarm{border-color:#e03131;background:#fff5f5} |
| 666 | .statblk.alarm{border-color:var(--danger);background:var(--danger-bg)} |
| 667 | 667 | .statdid{font-size:.8rem;color:var(--fg-dim)} |
| 668 | 668 | .statsum{font-size:.9rem;margin:.2rem 0 .4rem} |
| 669 | 669 | .stattbl{border-collapse:collapse;font-size:.8rem;width:100%} |
| 670 | 670 | .stattbl th{text-align:left;color:var(--fg-faint);font-weight:600;padding:.15rem .4rem .15rem 0} |
| 671 | 671 | .stattbl td{padding:.15rem .4rem .15rem 0;border-top:1px solid #f1f1f1} |
| 672 | 672 | .stattbl tr.chosen td{font-weight:600;background:#f8f9ff} |
| 673 | | .alarmnote{color:#c92a2a;font-size:.82rem;margin:.4rem 0 0} |
| 674 | | .ok{color:#2b8a3e}.bad{color:#c92a2a} |
| 673 | .alarmnote{color:var(--danger);font-size:.82rem;margin:.4rem 0 0} |
| 674 | .ok{color:var(--ok)}.bad{color:var(--danger)} |
| 675 | 675 | .ptabs{display:flex;gap:.15rem;border-bottom:1px solid var(--line);margin:.6rem 0 .3rem;flex-wrap:wrap} |
| 676 | 676 | .ptab{padding:.35rem .7rem;font-size:.88rem;color:var(--fg-dim);text-decoration:none;border-bottom:2px solid transparent} |
| 677 | 677 | .ptab:hover{color:var(--fg)} |
| … | … | @@ -693,7 +693,7 @@ a:focus-visible,button:focus-visible,input:focus-visible,textarea:focus-visible, |
| 693 | 693 | .likebtn,.rpbtn{padding:.3rem .45rem;margin:-.3rem -.1rem} |
| 694 | 694 | .likebtn:active,.rpbtn:active,.followbtn:active{transform:scale(.88)} |
| 695 | 695 | .likebtn[disabled],.rpbtn[disabled],.followbtn[disabled]{opacity:.55;cursor:default} |
| 696 | | .likebtn.failed,.rpbtn.failed,.followbtn.failed{color:#c92a2a;animation:shake .25s} |
| 696 | .likebtn.failed,.rpbtn.failed,.followbtn.failed{color:var(--danger);animation:shake .25s} |
| 697 | 697 | @keyframes shake{25%{transform:translateX(-2px)}75%{transform:translateX(2px)}} |
| 698 | 698 | /* Keyboard users get the same affordance the mouse does — these are real buttons, so make focus visible. */ |
| 699 | 699 | .likebtn:focus-visible,.rpbtn:focus-visible,.followbtn:focus-visible,.replyc:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:.3rem} |
| … | … | @@ -706,7 +706,7 @@ a:focus-visible,button:focus-visible,input:focus-visible,textarea:focus-visible, |
| 706 | 706 | .fol{display:inline-block;margin:.1rem .3rem .1rem 0;color:#356} |
| 707 | 707 | .folmore{color:var(--fg-faint)} |
| 708 | 708 | .profgraph{margin:.4rem 0 0;font-size:.9rem;color:var(--fg-dim)} |
| 709 | | .cc{font-size:.8rem;color:var(--fg-faint);margin-left:auto}.cc.over{color:#b91c1c;font-weight:600} |
| 709 | .cc{font-size:.8rem;color:var(--fg-faint);margin-left:auto}.cc.over{color:var(--danger-text);font-weight:600} |
| 710 | 710 | .proform label{font-size:.85rem;color:var(--fg-dim)} |
| 711 | 711 | .proform input,.proform textarea{width:100%;box-sizing:border-box;font:inherit;padding:.4rem;border:1px solid var(--line);border-radius:.3rem} |
| 712 | 712 | .proform button{font:inherit;padding:.35rem .9rem;cursor:pointer} |
| … | … | @@ -717,11 +717,10 @@ a:focus-visible,button:focus-visible,input:focus-visible,textarea:focus-visible, |
| 717 | 717 | .imgprev .thumb img{width:140px;height:100px;object-fit:cover;border-radius:.3rem;background:var(--bg-soft)} |
| 718 | 718 | .imgprev .thumb input,.imgprev .thumb button{font:inherit;font-size:.75rem;padding:.2rem;width:100%;box-sizing:border-box} |
| 719 | 719 | .imgprev .thumb button{cursor:pointer} |
| 720 | | @media(prefers-color-scheme:dark){body{background:#111;color:#eee}a,.tag{color:#9ec5ff}.post{border-color:#333} |
| 721 | | .post:hover{background:#191919}.focus .post:hover,details.post.collapsed:not([open]):hover{background:none} |
| 722 | | .controls select,.controls button{background:#222;color:#eee;border:1px solid #444} |
| 723 | | .badge{background:#1e3a5f;color:#9ec5ff}.lbl{background:#4a1e1e;color:#f8b4b4}.meta,.meta .did,.who{color:#aaa} |
| 724 | | .pfp,.pfp.none{background:#374151}.profdid code{color:#9ca3af}.meta .permalink{color:#aaa}.cc{color:#9ca3af}} |
| 720 | /* The base layer's dark patch lived here: 5 lines hand-repainting body, a/.tag, .post, .post:hover, |
| 721 | .controls, .badge, .lbl, .meta/.did/.who/.permalink, .pfp, .profdid and .cc. Every one of those now |
| 722 | reads from a token, so the single :root override in the design pass below covers them and this block |
| 723 | had nothing left to do. It existed only because those rules were written as literals. */ |
| 725 | 724 | |
| 726 | 725 | /* ── design pass ────────────────────────────────────────────────────────────────────────────────── |
| 727 | 726 | Everything above grew rule-by-rule as features landed and had no shared scale: spacing was ad-hoc, |
| … | … | @@ -736,6 +735,17 @@ a:focus-visible,button:focus-visible,input:focus-visible,textarea:focus-visible, |
| 736 | 735 | --fg:#111; --fg-dim:#5c6672; --fg-faint:#6b7480; |
| 737 | 736 | --bg:#fff; --bg-soft:#f7f8fa; --line:#e6e8eb; --line-soft:#f0f1f3; |
| 738 | 737 | --accent:#1a56db; --like:#e0245e; --repost:#17bf63; |
| 738 | /* Semantic colours. These existed only as literals, which is why the dark patch below had to |
| 739 | hand-repaint every element that used one. Measured on --bg #fff: --danger-text 6.47:1 and --lens |
| 740 | 5.67:1 pass AA for text. Two were corrected on the way in rather than tokenising a known-failing |
| 741 | value a second time — --ok was #2b8a3e (4.37:1, text, just under), --bookmark was #f59f00 |
| 742 | (2.13:1 as an icon, under even the 3:1 non-text bar). --warn is only ever a border, where 3:1 |
| 743 | applies and 3.25:1 clears it. */ |
| 744 | --danger:#c92a2a; --danger-text:#b91c1c; --danger-bg:#fde8e8; |
| 745 | --warn:#b8860b; --ok:#2a833b; --bookmark:#c77800; --badge-bg:#e8f0fe; |
| 746 | /* The lens family names a FOREIGN source — content this node relays but does not hold. Audit #45 |
| 747 | lists that distinction as load-bearing, so it stays a visible treatment, not a hint. */ |
| 748 | --lens:#3b5bdb; --lens-line:#cbd5e1; --lens-edge:#dbe4ff; |
| 739 | 749 | --s1:.25rem; --s2:.5rem; --s3:.75rem; --s4:1rem; --s5:1.5rem; --s6:2rem; |
| 740 | 750 | /* Radii and type land on whole pixels at a 16px root. The previous values (6/10px, and |
| 741 | 751 | 12.48/13.6/15.2/16.8/21.6px) were on no grid at all, which is what fractional rem buys you: |
| … | … | @@ -748,7 +758,7 @@ a:focus-visible,button:focus-visible,input:focus-visible,textarea:focus-visible, |
| 748 | 758 | } |
| 749 | 759 | body{font-family:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,sans-serif; |
| 750 | 760 | max-width:640px;margin:0 auto;padding:var(--s5) var(--s4) var(--s6);color:var(--fg); |
| 751 | | line-height:1.55;-webkit-font-smoothing:antialiased;font-size:var(--f2)} |
| 761 | line-height:1.55;-webkit-font-smoothing:antialiased;font-size:var(--f2);background:var(--bg)} |
| 752 | 762 | h1{display:flex;align-items:center;gap:var(--s2);font-size:var(--f4);letter-spacing:-.01em;margin:0 0 var(--s3)} |
| 753 | 763 | h1 small{font-size:var(--f1)} |
| 754 | 764 | /* The search form is a fixed 8rem and a flex item defaults to min-width:auto, so on a nowrap row it |
| … | … | @@ -816,7 +826,13 @@ nav a[aria-current=page]{color:var(--fg);font-weight:600;border-bottom-color:var |
| 816 | 826 | } |
| 817 | 827 | @media(prefers-color-scheme:dark){ |
| 818 | 828 | :root{--fg:#e8eaed;--fg-dim:#9aa4b2;--fg-faint:#79838f;--bg:#111;--bg-soft:#191b1f; |
| 819 | | --line:#2b2f36;--line-soft:#23262b;--accent:#9ec5ff} |
| 829 | --line:#2b2f36;--line-soft:#23262b;--accent:#9ec5ff; |
| 830 | /* Measured on --bg #111: danger-text 10.95:1, ok 10.84:1, bookmark 8.85:1, lens 9.47:1. |
| 831 | --danger keeps its light value because it is a fixed button background that white sits on |
| 832 | (5.46:1) rather than something read against the page. */ |
| 833 | --danger:#c92a2a;--danger-text:#f8b4b4;--danger-bg:#4a1e1e; |
| 834 | --warn:#e3b341;--ok:#4ade80;--bookmark:#f59f00;--badge-bg:#1e3a5f; |
| 835 | --lens:#a5b4fc;--lens-line:#3b4252;--lens-edge:#2d3a5f} |
| 820 | 836 | .post .media img{border-color:var(--line)} |
| 821 | 837 | .composer textarea{background:#0e0f12;color:var(--fg)} |
| 822 | 838 | #post-btn{background:var(--accent);color:#0b0d10} |