Website for the Lede browser extension.
0
fork

Configure Feed

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

Polish landing motion, voice, and micro-interactions

Add hero whisper and footer tagline; warm FAQ eyebrow; devtools console nod.
Smooth staggered reveals and scroll entrances; hover feedback on highlights,
logo, demo iframe, and buttons; respect prefers-reduced-motion.

+136 -28
+4 -1
src/components/SiteFooter.astro
··· 8 8 9 9 <footer class="site-footer"> 10 10 <div class="wrap footer-inner"> 11 - <span class="font-display" style="font-weight: 700; color: var(--color-ink)">Lede</span> 11 + <div class="footer-brand-block"> 12 + <span class="font-display" style="font-weight: 700; color: var(--color-ink)">Lede</span> 13 + <p class="footer-whisper">Built for tab-hoppers who still read the good parts.</p> 14 + </div> 12 15 <div class="footer-links"> 13 16 <a href={tangled} target="_blank" rel="noopener noreferrer">Project page</a> 14 17 <a href="#install">Install</a>
+1 -1
src/components/sections/FAQCompact.astro
··· 12 12 aria-labelledby="faq-heading" 13 13 > 14 14 <header class="section__head"> 15 - <p class="eyebrow">Questions</p> 15 + <p class="eyebrow">Curious?</p> 16 16 <h2 id="faq-heading" class="heading-xl">FAQ</h2> 17 17 </header> 18 18 <div class="faq-stack">
+6 -3
src/components/sections/HeroWithProof.astro
··· 23 23 Get the gist of any page in a few seconds, and find out whether 24 24 you want to read more. 25 25 </p> 26 + <p class="hero-whisper lede--tight reveal-item" style="--i: 3"> 27 + Main point first—rabbit holes optional. 28 + </p> 26 29 <ul 27 30 class="hero-highlights reveal-item" 28 - style="--i: 3" 31 + style="--i: 4" 29 32 aria-label="Product highlights" 30 33 > 31 34 <li> ··· 85 88 <span>Privacy-first</span> 86 89 </li> 87 90 </ul> 88 - <div class="actions reveal-item" style="--i: 4"> 91 + <div class="actions reveal-item" style="--i: 5"> 89 92 <a class="btn btn--primary" href="#install">Install (beta)</a> 90 93 <a 91 94 class="btn btn--secondary" ··· 97 100 </a> 98 101 </div> 99 102 </div> 100 - <figure class="hero-proof reveal-item" style="--i: 5"> 103 + <figure class="hero-proof reveal-item" style="--i: 6"> 101 104 <div class="hero-proof__column"> 102 105 <div class="hero-proof__demo-wrap"> 103 106 <div class="hero-proof__frame hero-proof__frame--demo">
+11
src/layouts/BaseLayout.astro
··· 69 69 }); 70 70 })(); 71 71 </script> 72 + <script is:inline> 73 + try { 74 + if (typeof console !== "undefined" && console.log) { 75 + console.log( 76 + "%cLede%c — If you found this in the console, you already get the product.", 77 + "font-weight:700;font-family:Sora,system-ui,sans-serif;color:#F15B2F", 78 + "font-weight:500;color:inherit" 79 + ); 80 + } 81 + } catch (e) {} 82 + </script> 72 83 </body> 73 84 </html>
+114 -23
src/styles/global.css
··· 76 76 --radius-pill: 14px; 77 77 78 78 --ease-out: cubic-bezier(0.22, 1, 0.36, 1); 79 + /* Softer deceleration for first-paint choreography (no bounce) */ 80 + --ease-reveal: cubic-bezier(0.16, 1, 0.3, 1); 79 81 --ease-out-disclosure: cubic-bezier(0.22, 1, 0.36, 1); 80 - --duration-enter: 0.52s; 82 + --duration-enter: 0.74s; 81 83 --duration-disclosure: 0.42s; 82 84 /* Fixed caps for <details> collapse — animating 0fr→1fr is skipped inconsistently in browsers */ 83 85 --disclosure-collapse-max: min(92vh, 52rem); ··· 408 410 max-height: 1.65rem; 409 411 flex-shrink: 0; 410 412 display: block; 413 + transform-origin: 55% 60%; 414 + } 415 + 416 + @media (prefers-reduced-motion: no-preference) { 417 + .brand-lockup__mark { 418 + transition: transform 0.28s var(--ease-out); 419 + } 420 + 421 + .brand-lockup:hover .brand-lockup__mark { 422 + transform: rotate(-5deg) scale(1.04); 423 + } 411 424 } 412 425 413 426 .nav { ··· 612 625 transform: translateY(-1px); 613 626 } 614 627 628 + .btn--secondary:active { 629 + transform: translateY(1px); 630 + } 631 + 615 632 /* ——— Sections ——— */ 616 633 .section { 617 634 padding-block: var(--section-y); ··· 746 763 color: var(--color-ink-secondary); 747 764 } 748 765 749 - /* ——— Motion: staggered reveal (light settle — mostly transform, barely-there opacity) ——— */ 766 + .footer-brand-block { 767 + display: flex; 768 + flex-direction: column; 769 + align-items: flex-start; 770 + gap: var(--space-3xs); 771 + min-width: min(100%, 16rem); 772 + } 773 + 774 + .footer-whisper { 775 + margin: 0; 776 + max-width: 22rem; 777 + font-size: 0.8125rem; 778 + line-height: var(--leading-ui); 779 + color: var(--color-ink-muted); 780 + letter-spacing: -0.01em; 781 + } 782 + 783 + /* ——— Motion: staggered reveal (first load — opacity + transform, smooth ease-out) ——— */ 750 784 .reveal-group { 751 - --stagger: 0.06s; 785 + --stagger: 0.09s; 752 786 } 753 787 754 788 .reveal-item { 755 - opacity: 0.92; 756 - transform: translateY(10px); 757 - animation: reveal-in var(--duration-enter) var(--ease-out) forwards; 789 + animation: reveal-in var(--duration-enter) var(--ease-reveal) both; 758 790 animation-delay: calc(var(--i, 0) * var(--stagger)); 759 791 } 760 792 761 793 @keyframes reveal-in { 794 + from { 795 + opacity: 0; 796 + transform: translateY(1.125rem); 797 + } 798 + 762 799 to { 763 800 opacity: 1; 764 801 transform: translateY(0); ··· 794 831 .nav a, 795 832 .footer-links a, 796 833 .brand-lockup, 797 - .journey-strip__cell a { 834 + .journey-strip__cell a, 835 + .hero-highlights li { 798 836 transition: none; 799 837 } 800 838 ··· 809 847 .journey-strip__cell a:hover { 810 848 transform: none; 811 849 } 850 + 851 + .brand-lockup:hover .brand-lockup__mark { 852 + transform: none; 853 + } 854 + 855 + .hero-highlights li:hover .hero-highlights__icon svg { 856 + transform: none; 857 + } 858 + 859 + .hero-proof__demo-wrap:hover .extension-demo { 860 + transform: none; 861 + } 812 862 } 813 863 814 864 /* ========= Redesign: masthead hero + proof, install journey, editorial ========= */ ··· 844 894 margin: 0 0 var(--space-sm); 845 895 } 846 896 897 + /* Hero: light wit — journalism-flavored, not gimmicky */ 898 + .hero-whisper { 899 + margin: 0; 900 + font-family: var(--font-body); 901 + font-size: clamp(0.9375rem, 0.35vw + 0.88rem, 1.0625rem); 902 + font-weight: 500; 903 + line-height: var(--leading-ui); 904 + color: color-mix(in oklch, var(--color-brand) 28%, var(--color-ink-muted)); 905 + letter-spacing: -0.01em; 906 + } 907 + 847 908 .lede--tight { 848 909 max-width: 32em; 849 910 font-size: var(--text-sm); ··· 879 940 880 941 .hero-mast__copy .display-hero, 881 942 .hero-mast__copy .deck, 882 - .hero-mast__copy .lede { 943 + .hero-mast__copy .lede, 944 + .hero-mast__copy .hero-whisper { 883 945 margin: 0; 884 946 } 885 947 ··· 912 974 letter-spacing: -0.012em; 913 975 line-height: var(--leading-ui); 914 976 color: var(--color-ink-secondary); 977 + border-radius: var(--radius-sm); 978 + margin-inline: calc(var(--space-2xs) * -1); 979 + padding: var(--space-3xs) var(--space-2xs); 980 + transition: color 0.22s var(--ease-out), background-color 0.22s var(--ease-out); 981 + } 982 + 983 + .hero-highlights li:hover { 984 + color: var(--color-ink); 985 + background: color-mix(in oklch, var(--color-brand-soft) 55%, transparent); 915 986 } 916 987 917 988 .hero-highlights__icon { ··· 930 1001 height: 1.125rem; 931 1002 } 932 1003 933 - .hero-mast__copy > p:not(.eyebrow):not(.deck):not(.lede) { 1004 + @media (prefers-reduced-motion: no-preference) { 1005 + .hero-highlights__icon svg { 1006 + transition: transform 0.26s var(--ease-out); 1007 + } 1008 + 1009 + .hero-highlights li:hover .hero-highlights__icon svg { 1010 + transform: scale(1.07) rotate(-6deg); 1011 + } 1012 + } 1013 + 1014 + .hero-mast__copy > p:not(.eyebrow):not(.deck):not(.lede):not(.hero-whisper) { 934 1015 margin: 0; 935 1016 } 936 1017 ··· 1021 1102 0 12px 28px oklch(0% 0 0 / 0.07); 1022 1103 } 1023 1104 1105 + @media (prefers-reduced-motion: no-preference) { 1106 + .hero-proof .extension-demo { 1107 + transition: transform 0.34s var(--ease-out); 1108 + } 1109 + 1110 + .hero-proof__demo-wrap:hover .extension-demo { 1111 + transform: translateY(-5px); 1112 + } 1113 + } 1114 + 1024 1115 @media (max-width: 440px) { 1025 1116 .hero-proof__frame--demo { 1026 1117 justify-content: flex-start; ··· 1035 1126 1036 1127 @media (prefers-reduced-motion: no-preference) { 1037 1128 .hero-proof__frame:not(.hero-proof__frame--demo) { 1038 - animation: hero-frame-in 0.85s var(--ease-out) both; 1039 - animation-delay: 0.12s; 1129 + animation: hero-frame-in 0.95s var(--ease-reveal) both; 1130 + animation-delay: 0.14s; 1040 1131 } 1041 1132 1042 1133 @keyframes hero-frame-in { 1043 1134 from { 1044 1135 opacity: 0; 1045 - transform: translateY(16px) scale(0.985); 1136 + transform: translateY(1.125rem) scale(0.988); 1046 1137 } 1047 1138 to { 1048 1139 opacity: 1; ··· 1485 1576 1486 1577 @keyframes reveal-scroll-enter { 1487 1578 from { 1488 - opacity: 0.9; 1489 - transform: translateY(12px); 1579 + opacity: 0.82; 1580 + transform: translateY(1rem); 1490 1581 } 1491 1582 1492 1583 to { ··· 1498 1589 @media (prefers-reduced-motion: no-preference) { 1499 1590 @supports (animation-timeline: view(block)) { 1500 1591 .reveal-scroll { 1501 - opacity: 0.9; 1502 - transform: translateY(12px); 1503 - /* Scroll timeline drives progress; ease-out maps scroll position → keyframes for a soft finish */ 1592 + opacity: 0.82; 1593 + transform: translateY(1rem); 1594 + /* Scroll timeline drives progress; ease maps scroll position → keyframes for a soft finish */ 1504 1595 animation: reveal-scroll-enter linear forwards; 1505 1596 animation-timeline: view(block); 1506 - animation-range: entry 12% cover 48%; 1507 - animation-timing-function: var(--ease-out); 1597 + animation-range: entry 8% cover 52%; 1598 + animation-timing-function: var(--ease-reveal); 1508 1599 } 1509 1600 } 1510 1601 1511 1602 @supports not (animation-timeline: view(block)) { 1512 1603 .reveal-scroll:not(.reveal-scroll--visible) { 1513 - opacity: 0.9; 1514 - transform: translateY(12px); 1604 + opacity: 0.82; 1605 + transform: translateY(1rem); 1515 1606 } 1516 1607 1517 1608 .reveal-scroll.reveal-scroll--visible { 1518 1609 opacity: 1; 1519 1610 transform: none; 1520 1611 transition: 1521 - opacity 0.42s var(--ease-out), 1522 - transform 0.5s var(--ease-out); 1612 + opacity 0.55s var(--ease-reveal), 1613 + transform 0.62s var(--ease-reveal); 1523 1614 } 1524 1615 } 1525 1616 }