Practical Betterments
banner
practicallybetter.bsky.social
Practical Betterments
@practicallybetter.bsky.social
A collection of one-off actions that improve your life continuously — however marginally.

practicalbetterments.com
Pinned
Practical Betterments are not a replacement for therapy, surgery, radical societal change, or even just being a reasonable adult. Cutting the end off your toothbrush will not find you true love.

But wouldn't it be easier to find true love without lugging round 5g of unnecessary toothbrush weight?
Practical betterments
A collection of one-off actions to improve your life continuously — however marginally
practicalbetterments.com
Apply for or claim citizenship of another country

@bsky.app can you fix the link previews so they don't concatenate the elements from inlined svgs. See example below. Thanks</div> <a href="https://practicalbetterments.com/apply-for-citizenship-of-another-country/" target="_blank" rel="noopener" class="block mt-2 border rounded overflow-hidden w-[calc(100%+3.5rem)] -ml-[3.5rem] no-card-link"> <img src="https://cdn.bsky.app/img/feed_thumbnail/plain/did:plc:jwxd2axqquyd5qlcikd6hesz/bafkreiefae4fcpoiwugw6fv322iwn5yx6hsvareqsuq3vd7mzjm2paqzly@jpeg" class="w-full h-40 object-cover" loading="lazy"> <div class="p-2"> <div class="text-sm font-semibold truncate">Apply for or claim citizenship of anotherPeruBurkina FasoFranceFrench PolynesiaNew CaledoniaLibyaBelarusPakistanIndonesiaYemenMadagascarBoliviaCôte d'IvoireAlgeriaSwitzerlandCameroonMacedoniaBotswanaK...</div> <div class="text-xs text-gray-500 truncate">Is your home country, too cold, too hot, or too rapidly sliding into authoritarianism?</div> </div> <div class="border-t px-2 py-2 text-sm text-gray-600 flex items-center gap-2"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M2 12h20"/><path d="M12 2a15.3 15.3 0 0 1 0 20"/><path d="M12 2a15.3 15.3 0 0 0 0 20"/></svg> <span class="truncate">practicalbetterments.com</span> </div> </a> <div class="mt-3 text-xs text-gray-500 flex items-center gap-2 whitespace-nowrap overflow-hidden w-[calc(100%+3.5rem)] -ml-[3.5rem]"> <span>February 18, 2025 at 4:42 PM</span> </div> <div class="border-t my-2 w-[calc(100%+3.5rem)] -ml-[3.5rem]"></div> <div class="mt-3 flex items-center justify-between text-gray-600 text-sm w-[calc(100%+3.5rem)] -ml-[3.5rem] no-card-link" data-controller="bluesky-interactions"> <div class="flex items-center justify-between w-[300px] pr-4 no-card-link"> <div class="hidden" data-post-text-uri="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lihpdwomis2v"> Apply for or claim citizenship of another country<br><br><a href="https://bsky.app/profile/did:plc:z72i7hdynmk6r22z27h6tvur" class="hover:underline text-blue-600 dark:text-sky-400 no-card-link" target="_blank" rel="noopener" data-link="bsky-mention">@bsky.app</a> can you fix the link previews so they don't concatenate the <title> elements from inlined svgs. See example below. Thanks </div> <button type="button" class="flex items-center gap-1 hover:text-black no-card-link" data-action="click->bluesky-auth#requireConnection click->bluesky-interactions#reply" data-bluesky-interactions-reply-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lihpdwomis2v" data-bluesky-interactions-reply-cid-param="bafyreiapbrlfwu24wjfkamfm2nw6qnoi2a65y7x77mwrdyazblonpjhpgy" data-bluesky-interactions-reply-root-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lihpdwomis2v" data-bluesky-interactions-reply-root-cid-param="bafyreiapbrlfwu24wjfkamfm2nw6qnoi2a65y7x77mwrdyazblonpjhpgy" data-bluesky-interactions-reply-author-name-param="Practical Betterments" data-bluesky-interactions-reply-author-avatar-param="https://cdn.bsky.app/img/avatar/plain/did:plc:jwxd2axqquyd5qlcikd6hesz/bafkreifuam6bjsq4c4loo6qtqznl5yhmpw3ij72xixli6pytuabiffhg44@jpeg" data-bluesky-interactions-post-path-param="/bsky/practicallybetter.bsky.social/post/3lihpdwomis2v" title="Reply" style="pointer-events: auto; cursor: pointer; z-index: 10; position: relative;"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15a4 4 0 0 1-4 4H7l-4 4V7a4 4 0 0 1 4-4h10a4 4 0 0 1 4 4z"/></svg> <span data-bluesky-interactions-target="replyCount">1</span> </button> <div class="relative no-card-link" data-controller="bluesky-repost-menu" data-bluesky-repost-menu-uri-value="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lihpdwomis2v" data-bluesky-repost-menu-cid-value="bafyreiapbrlfwu24wjfkamfm2nw6qnoi2a65y7x77mwrdyazblonpjhpgy" data-bluesky-repost-menu-repost-uri-value="" data-bluesky-repost-menu-is-reposted-value="false" data-bluesky-repost-menu-author-handle-value="practicallybetter.bsky.social" data-bluesky-repost-menu-post-text-value="Apply for or claim citizenship of another country @bsky.app can you fix the link previews so they don't concatenate the <title> elements from inlined svgs. See example below. Thanks" style="pointer-events:auto; cursor:pointer;"> <button type="button" class="flex items-center gap-1 hover:text-black " data-action="click->bluesky-repost-menu#toggleMenu" data-bluesky-interactions-target="repostButton" title="Repost"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg> </button> <div class="hidden absolute left-0 bottom-full mb-3 w-48 rounded-2xl border border-white/10 bg-[#1C2333] text-white shadow-xl overflow-hidden z-50" data-bluesky-repost-menu-target="menu"> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-repost-menu#repost"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg> <span>Repost</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-repost-menu#quote"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg> <span>Quote post</span> </button> </div> </div> <button type="button" class="flex items-center gap-1 hover:text-black no-card-link " data-action="click->bluesky-auth#requireConnection click->bluesky-interactions#toggleLike" data-bluesky-interactions-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lihpdwomis2v" data-bluesky-interactions-cid-param="bafyreiapbrlfwu24wjfkamfm2nw6qnoi2a65y7x77mwrdyazblonpjhpgy" data-bluesky-interactions-like-uri-param="" data-bluesky-interactions-target="likeButton" title="Like"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 1 0-7.78 7.78L12 21.23l8.84-8.84a5.5 5.5 0 0 0 0-7.78z"/></svg> <span data-bluesky-interactions-target="likeCount">1</span> </button> </div> <div class="flex items-center gap-4 text-gray-500"> <button type="button" class="flex items-center hover:text-black no-card-link" data-controller="share" data-share-url-value="https://oauth.lightnews.app/bsky/practicallybetter.bsky.social/post/3lihpdwomis2v" data-share-title-value="Practical Betterments on Lightnews" data-share-text-value="Apply for or claim citizenship of another country @bsky.app can you fix the link previews so they don't concatenate the <title> elements fro…" data-action="click->share#shareSystem" title="Share" style="pointer-events:auto; cursor:pointer;"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 12v7a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-7"/><polyline points="16 6 12 2 8 6"/><line x1="12" y1="2" x2="12" y2="15"/></svg> </button> <div class="relative no-card-link" data-controller="bluesky-options" data-bluesky-options-text-value="Apply for or claim citizenship of another country @bsky.app can you fix the link previews so they don't concatenate the <title> elements from inlined svgs. See example below. Thanks" data-bluesky-options-author-handle-value="practicallybetter.bsky.social" data-bluesky-options-author-did-value="did:plc:jwxd2axqquyd5qlcikd6hesz" data-bluesky-options-muted-value="false" data-bluesky-options-blocking-uri-value="" data-bluesky-options-own-value="false" data-bluesky-options-delete-url-value="" data-bluesky-options-post-element-selector-value='[data-card-type="bsky-post"]'> <button type="button" class="inline-flex items-center" data-action="click->bluesky-options#toggleMenu" aria-label="Post options"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="1"/><circle cx="19" cy="12" r="1"/><circle cx="5" cy="12" r="1"/></svg> </button> <div class="hidden absolute right-0 bottom-full mb-3 w-60 rounded-2xl border border-white/10 bg-[#1C2333] text-white shadow-xl overflow-hidden" data-bluesky-options-target="menu"> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-options#translate"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 4h16v16H4z"/><path d="M9 8h6"/><path d="M9 12h6"/><path d="M9 16h6"/></svg> </span> <span>Translate</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-options#copyText"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="8" y="8" width="12" height="12" rx="2"/><path d="M16 8V6a2 2 0 0 0-2-2h-8a2 2 0 0 0-2 2v8"/></svg> </span> <span>Copy post text</span> </button> <div class="border-t border-white/10"></div> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-options#muteAccount"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 9v6h3l5 5V4L7 9H4z"/><line x1="16" y1="9" x2="19" y2="12"/><line x1="19" y1="12" x2="16" y2="15"/></svg> </span> <span data-bluesky-options-target="muteLabel">Mute account</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-options#blockAccount"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 3h18v18H3z"/><path d="M3 3l18 18"/></svg> </span> <span data-bluesky-options-target="blockLabel">Block account</span> </button> </div> </div> </div> </div> </div> </div> </div> </div> <script> // Prevent navigation when clicking in avatar column area - must run in capture phase before global handler // Only initialize once to avoid duplicate listeners if (!window._avatarColumnNoNavInitialized) { window._avatarColumnNoNavInitialized = true; document.addEventListener('click', function(ev) { try { // Check if target itself has the class OR is inside an element with that class var avatarColumn = (ev.target.classList && ev.target.classList.contains('avatar-column-no-nav')) || (ev.target.closest && ev.target.closest('.avatar-column-no-nav')); if (avatarColumn) { // Only allow navigation if clicking directly on the avatar link itself var isAvatarLink = ev.target.tagName === 'A' && ev.target.href && ev.target.href.indexOf('/author') !== -1; if (!isAvatarLink) { ev.stopPropagation(); ev.stopImmediatePropagation(); ev.preventDefault(); return false; } } } catch(e) {} }, true); // Capture phase - runs BEFORE other handlers } </script> <div class="w-full border-y sm:border bg-white dark:bg-[#0C1220] bluesky-list-card digest-card card-clickable cursor-pointer group" data-href="/bsky/practicallybetter.bsky.social/post/3lhtscqaad22j" role="link" tabindex="0" data-card-type="bsky-post" onclick="if(!event.target.closest('.no-card-link')){ window.location = this.dataset.href }" onkeydown="if((event.key==='Enter' || event.key===' ') && !event.target.closest('.no-card-link')){ window.location = this.dataset.href }"> <div class="px-4 py-3"> <div class="flex items-start gap-4"> <div class="relative w-10 self-stretch flex justify-center no-card-link avatar-column-no-nav" style="min-height:40px; align-self:stretch" onclick="event.stopPropagation(); event.stopImmediatePropagation(); return false;" onkeydown="if(event.key==='Enter' || event.key===' '){ event.stopPropagation(); event.stopImmediatePropagation(); return false; }"> <a href="/author?bsky_handle=practicallybetter.bsky.social" class="no-card-link inline-block flex-shrink-0" aria-label="Practical Betterments" style="align-self: flex-start;"> <img src="https://cdn.bsky.app/img/avatar/plain/did:plc:jwxd2axqquyd5qlcikd6hesz/bafkreifuam6bjsq4c4loo6qtqznl5yhmpw3ij72xixli6pytuabiffhg44@jpeg" alt="practicallybetter.bsky.social" class="w-10 h-10 rounded-full relative z-10" loading="lazy"> </a> </div> <div class="flex-1 min-w-0 -mt-0.5"> <div> <div class="text-[1.1rem] sm:text-[1.15rem] font-semibold text-black flex items-center gap-1"> <a href="/author?bsky_handle=practicallybetter.bsky.social" class="truncate hover:underline text-black no-card-link">Practical Betterments</a> </div> <div class="text-gray-500 text-sm leading-4 -mt-0.5 truncate"> <a href="/author?bsky_handle=practicallybetter.bsky.social" class="hover:underline text-gray-500 no-card-link">@practicallybetter.bsky.social</a> </div> </div> <div class="mt-3 text-[1.2rem] leading-7 break-words text-gray-800 w-[calc(100%+3.5rem)] -ml-[3.5rem]"></div> <a href="https://practicalbetterments.com/put-your-money-into-a-savings-account/" target="_blank" rel="noopener" class="block mt-2 border rounded overflow-hidden w-[calc(100%+3.5rem)] -ml-[3.5rem] no-card-link"> <img src="https://cdn.bsky.app/img/feed_thumbnail/plain/did:plc:jwxd2axqquyd5qlcikd6hesz/bafkreig2sdorrquggjigmr3xzwsvgzykiy3zorg3wjgjfdlhm75kvdjkgq@jpeg" class="w-full h-40 object-cover" loading="lazy"> <div class="p-2"> <div class="text-sm font-semibold truncate">Put your money into a savings account</div> <div class="text-xs text-gray-500 truncate">This is financial advice.</div> </div> <div class="border-t px-2 py-2 text-sm text-gray-600 flex items-center gap-2"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M2 12h20"/><path d="M12 2a15.3 15.3 0 0 1 0 20"/><path d="M12 2a15.3 15.3 0 0 0 0 20"/></svg> <span class="truncate">practicalbetterments.com</span> </div> </a> <div class="mt-3 text-xs text-gray-500 flex items-center gap-2 whitespace-nowrap overflow-hidden w-[calc(100%+3.5rem)] -ml-[3.5rem]"> <span>February 10, 2025 at 6:42 PM</span> </div> <div class="border-t my-2 w-[calc(100%+3.5rem)] -ml-[3.5rem]"></div> <div class="mt-3 flex items-center justify-between text-gray-600 text-sm w-[calc(100%+3.5rem)] -ml-[3.5rem] no-card-link" data-controller="bluesky-interactions"> <div class="flex items-center justify-between w-[300px] pr-4 no-card-link"> <div class="hidden" data-post-text-uri="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lhtscqaad22j"> </div> <button type="button" class="flex items-center gap-1 hover:text-black no-card-link" data-action="click->bluesky-auth#requireConnection click->bluesky-interactions#reply" data-bluesky-interactions-reply-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lhtscqaad22j" data-bluesky-interactions-reply-cid-param="bafyreigl567ymaa4ja7a3xgm47qcnfav3fuwl3dtzjpej5t6gk5w2hq3xm" data-bluesky-interactions-reply-root-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lhtscqaad22j" data-bluesky-interactions-reply-root-cid-param="bafyreigl567ymaa4ja7a3xgm47qcnfav3fuwl3dtzjpej5t6gk5w2hq3xm" data-bluesky-interactions-reply-author-name-param="Practical Betterments" data-bluesky-interactions-reply-author-avatar-param="https://cdn.bsky.app/img/avatar/plain/did:plc:jwxd2axqquyd5qlcikd6hesz/bafkreifuam6bjsq4c4loo6qtqznl5yhmpw3ij72xixli6pytuabiffhg44@jpeg" data-bluesky-interactions-post-path-param="/bsky/practicallybetter.bsky.social/post/3lhtscqaad22j" title="Reply" style="pointer-events: auto; cursor: pointer; z-index: 10; position: relative;"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15a4 4 0 0 1-4 4H7l-4 4V7a4 4 0 0 1 4-4h10a4 4 0 0 1 4 4z"/></svg> </button> <div class="relative no-card-link" data-controller="bluesky-repost-menu" data-bluesky-repost-menu-uri-value="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lhtscqaad22j" data-bluesky-repost-menu-cid-value="bafyreigl567ymaa4ja7a3xgm47qcnfav3fuwl3dtzjpej5t6gk5w2hq3xm" data-bluesky-repost-menu-repost-uri-value="" data-bluesky-repost-menu-is-reposted-value="false" data-bluesky-repost-menu-author-handle-value="practicallybetter.bsky.social" data-bluesky-repost-menu-post-text-value="" style="pointer-events:auto; cursor:pointer;"> <button type="button" class="flex items-center gap-1 hover:text-black " data-action="click->bluesky-repost-menu#toggleMenu" data-bluesky-interactions-target="repostButton" title="Repost"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg> </button> <div class="hidden absolute left-0 bottom-full mb-3 w-48 rounded-2xl border border-white/10 bg-[#1C2333] text-white shadow-xl overflow-hidden z-50" data-bluesky-repost-menu-target="menu"> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-repost-menu#repost"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg> <span>Repost</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-repost-menu#quote"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg> <span>Quote post</span> </button> </div> </div> <button type="button" class="flex items-center gap-1 hover:text-black no-card-link " data-action="click->bluesky-auth#requireConnection click->bluesky-interactions#toggleLike" data-bluesky-interactions-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lhtscqaad22j" data-bluesky-interactions-cid-param="bafyreigl567ymaa4ja7a3xgm47qcnfav3fuwl3dtzjpej5t6gk5w2hq3xm" data-bluesky-interactions-like-uri-param="" data-bluesky-interactions-target="likeButton" title="Like"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 1 0-7.78 7.78L12 21.23l8.84-8.84a5.5 5.5 0 0 0 0-7.78z"/></svg> </button> </div> <div class="flex items-center gap-4 text-gray-500"> <button type="button" class="flex items-center hover:text-black no-card-link" data-controller="share" data-share-url-value="https://oauth.lightnews.app/bsky/practicallybetter.bsky.social/post/3lhtscqaad22j" data-share-title-value="Practical Betterments on Lightnews" data-share-text-value="" data-action="click->share#shareSystem" title="Share" style="pointer-events:auto; cursor:pointer;"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 12v7a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-7"/><polyline points="16 6 12 2 8 6"/><line x1="12" y1="2" x2="12" y2="15"/></svg> </button> <div class="relative no-card-link" data-controller="bluesky-options" data-bluesky-options-text-value="" data-bluesky-options-author-handle-value="practicallybetter.bsky.social" data-bluesky-options-author-did-value="did:plc:jwxd2axqquyd5qlcikd6hesz" data-bluesky-options-muted-value="false" data-bluesky-options-blocking-uri-value="" data-bluesky-options-own-value="false" data-bluesky-options-delete-url-value="" data-bluesky-options-post-element-selector-value='[data-card-type="bsky-post"]'> <button type="button" class="inline-flex items-center" data-action="click->bluesky-options#toggleMenu" aria-label="Post options"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="1"/><circle cx="19" cy="12" r="1"/><circle cx="5" cy="12" r="1"/></svg> </button> <div class="hidden absolute right-0 bottom-full mb-3 w-60 rounded-2xl border border-white/10 bg-[#1C2333] text-white shadow-xl overflow-hidden" data-bluesky-options-target="menu"> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-options#translate"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 4h16v16H4z"/><path d="M9 8h6"/><path d="M9 12h6"/><path d="M9 16h6"/></svg> </span> <span>Translate</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-options#copyText"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="8" y="8" width="12" height="12" rx="2"/><path d="M16 8V6a2 2 0 0 0-2-2h-8a2 2 0 0 0-2 2v8"/></svg> </span> <span>Copy post text</span> </button> <div class="border-t border-white/10"></div> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-options#muteAccount"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 9v6h3l5 5V4L7 9H4z"/><line x1="16" y1="9" x2="19" y2="12"/><line x1="19" y1="12" x2="16" y2="15"/></svg> </span> <span data-bluesky-options-target="muteLabel">Mute account</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-options#blockAccount"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 3h18v18H3z"/><path d="M3 3l18 18"/></svg> </span> <span data-bluesky-options-target="blockLabel">Block account</span> </button> </div> </div> </div> </div> </div> </div> </div> </div> <script> // Prevent navigation when clicking in avatar column area - must run in capture phase before global handler // Only initialize once to avoid duplicate listeners if (!window._avatarColumnNoNavInitialized) { window._avatarColumnNoNavInitialized = true; document.addEventListener('click', function(ev) { try { // Check if target itself has the class OR is inside an element with that class var avatarColumn = (ev.target.classList && ev.target.classList.contains('avatar-column-no-nav')) || (ev.target.closest && ev.target.closest('.avatar-column-no-nav')); if (avatarColumn) { // Only allow navigation if clicking directly on the avatar link itself var isAvatarLink = ev.target.tagName === 'A' && ev.target.href && ev.target.href.indexOf('/author') !== -1; if (!isAvatarLink) { ev.stopPropagation(); ev.stopImmediatePropagation(); ev.preventDefault(); return false; } } } catch(e) {} }, true); // Capture phase - runs BEFORE other handlers } </script> <div class="w-full border-y sm:border bg-white dark:bg-[#0C1220] bluesky-list-card digest-card card-clickable cursor-pointer group" data-href="/bsky/practicallybetter.bsky.social/post/3lhc47dhivs2x" role="link" tabindex="0" data-card-type="bsky-post" onclick="if(!event.target.closest('.no-card-link')){ window.location = this.dataset.href }" onkeydown="if((event.key==='Enter' || event.key===' ') && !event.target.closest('.no-card-link')){ window.location = this.dataset.href }"> <div class="px-4 py-3"> <div class="flex items-start gap-4"> <div class="relative w-10 self-stretch flex justify-center no-card-link avatar-column-no-nav" style="min-height:40px; align-self:stretch" onclick="event.stopPropagation(); event.stopImmediatePropagation(); return false;" onkeydown="if(event.key==='Enter' || event.key===' '){ event.stopPropagation(); event.stopImmediatePropagation(); return false; }"> <a href="/author?bsky_handle=practicallybetter.bsky.social" class="no-card-link inline-block flex-shrink-0" aria-label="Practical Betterments" style="align-self: flex-start;"> <img src="https://cdn.bsky.app/img/avatar/plain/did:plc:jwxd2axqquyd5qlcikd6hesz/bafkreifuam6bjsq4c4loo6qtqznl5yhmpw3ij72xixli6pytuabiffhg44@jpeg" alt="practicallybetter.bsky.social" class="w-10 h-10 rounded-full relative z-10" loading="lazy"> </a> </div> <div class="flex-1 min-w-0 -mt-0.5"> <div> <div class="text-[1.1rem] sm:text-[1.15rem] font-semibold text-black flex items-center gap-1"> <a href="/author?bsky_handle=practicallybetter.bsky.social" class="truncate hover:underline text-black no-card-link">Practical Betterments</a> </div> <div class="text-gray-500 text-sm leading-4 -mt-0.5 truncate"> <a href="/author?bsky_handle=practicallybetter.bsky.social" class="hover:underline text-gray-500 no-card-link">@practicallybetter.bsky.social</a> </div> </div> <div class="mt-3 text-[1.2rem] leading-7 break-words text-gray-800 w-[calc(100%+3.5rem)] -ml-[3.5rem]"></div> <a href="https://practicalbetterments.com/relocate-things-that-drip-over-things-that-collect-drips/" target="_blank" rel="noopener" class="block mt-2 border rounded overflow-hidden w-[calc(100%+3.5rem)] -ml-[3.5rem] no-card-link"> <img src="https://cdn.bsky.app/img/feed_thumbnail/plain/did:plc:jwxd2axqquyd5qlcikd6hesz/bafkreiamyssjzzkligszgof4vnfhi6qmrt73trrweak34tnij3obobl6cy@jpeg" class="w-full h-40 object-cover" loading="lazy"> <div class="p-2"> <div class="text-sm font-semibold truncate">Relocate things that drip over things that collect drips</div> <div class="text-xs text-gray-500 truncate"></div> </div> <div class="border-t px-2 py-2 text-sm text-gray-600 flex items-center gap-2"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M2 12h20"/><path d="M12 2a15.3 15.3 0 0 1 0 20"/><path d="M12 2a15.3 15.3 0 0 0 0 20"/></svg> <span class="truncate">practicalbetterments.com</span> </div> </a> <div class="mt-3 text-xs text-gray-500 flex items-center gap-2 whitespace-nowrap overflow-hidden w-[calc(100%+3.5rem)] -ml-[3.5rem]"> <span>February 3, 2025 at 5:51 PM</span> </div> <div class="border-t my-2 w-[calc(100%+3.5rem)] -ml-[3.5rem]"></div> <div class="mt-3 flex items-center justify-between text-gray-600 text-sm w-[calc(100%+3.5rem)] -ml-[3.5rem] no-card-link" data-controller="bluesky-interactions"> <div class="flex items-center justify-between w-[300px] pr-4 no-card-link"> <div class="hidden" data-post-text-uri="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lhc47dhivs2x"> </div> <button type="button" class="flex items-center gap-1 hover:text-black no-card-link" data-action="click->bluesky-auth#requireConnection click->bluesky-interactions#reply" data-bluesky-interactions-reply-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lhc47dhivs2x" data-bluesky-interactions-reply-cid-param="bafyreih4odl4j7m6sx5a2rmelvj66y7dzkxz4b6pgzuvsen26g3b7h2t4q" data-bluesky-interactions-reply-root-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lhc47dhivs2x" data-bluesky-interactions-reply-root-cid-param="bafyreih4odl4j7m6sx5a2rmelvj66y7dzkxz4b6pgzuvsen26g3b7h2t4q" data-bluesky-interactions-reply-author-name-param="Practical Betterments" data-bluesky-interactions-reply-author-avatar-param="https://cdn.bsky.app/img/avatar/plain/did:plc:jwxd2axqquyd5qlcikd6hesz/bafkreifuam6bjsq4c4loo6qtqznl5yhmpw3ij72xixli6pytuabiffhg44@jpeg" data-bluesky-interactions-post-path-param="/bsky/practicallybetter.bsky.social/post/3lhc47dhivs2x" title="Reply" style="pointer-events: auto; cursor: pointer; z-index: 10; position: relative;"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15a4 4 0 0 1-4 4H7l-4 4V7a4 4 0 0 1 4-4h10a4 4 0 0 1 4 4z"/></svg> </button> <div class="relative no-card-link" data-controller="bluesky-repost-menu" data-bluesky-repost-menu-uri-value="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lhc47dhivs2x" data-bluesky-repost-menu-cid-value="bafyreih4odl4j7m6sx5a2rmelvj66y7dzkxz4b6pgzuvsen26g3b7h2t4q" data-bluesky-repost-menu-repost-uri-value="" data-bluesky-repost-menu-is-reposted-value="false" data-bluesky-repost-menu-author-handle-value="practicallybetter.bsky.social" data-bluesky-repost-menu-post-text-value="" style="pointer-events:auto; cursor:pointer;"> <button type="button" class="flex items-center gap-1 hover:text-black " data-action="click->bluesky-repost-menu#toggleMenu" data-bluesky-interactions-target="repostButton" title="Repost"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg> </button> <div class="hidden absolute left-0 bottom-full mb-3 w-48 rounded-2xl border border-white/10 bg-[#1C2333] text-white shadow-xl overflow-hidden z-50" data-bluesky-repost-menu-target="menu"> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-repost-menu#repost"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg> <span>Repost</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-repost-menu#quote"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg> <span>Quote post</span> </button> </div> </div> <button type="button" class="flex items-center gap-1 hover:text-black no-card-link " data-action="click->bluesky-auth#requireConnection click->bluesky-interactions#toggleLike" data-bluesky-interactions-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lhc47dhivs2x" data-bluesky-interactions-cid-param="bafyreih4odl4j7m6sx5a2rmelvj66y7dzkxz4b6pgzuvsen26g3b7h2t4q" data-bluesky-interactions-like-uri-param="" data-bluesky-interactions-target="likeButton" title="Like"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 1 0-7.78 7.78L12 21.23l8.84-8.84a5.5 5.5 0 0 0 0-7.78z"/></svg> <span data-bluesky-interactions-target="likeCount">1</span> </button> </div> <div class="flex items-center gap-4 text-gray-500"> <button type="button" class="flex items-center hover:text-black no-card-link" data-controller="share" data-share-url-value="https://oauth.lightnews.app/bsky/practicallybetter.bsky.social/post/3lhc47dhivs2x" data-share-title-value="Practical Betterments on Lightnews" data-share-text-value="" data-action="click->share#shareSystem" title="Share" style="pointer-events:auto; cursor:pointer;"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 12v7a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-7"/><polyline points="16 6 12 2 8 6"/><line x1="12" y1="2" x2="12" y2="15"/></svg> </button> <div class="relative no-card-link" data-controller="bluesky-options" data-bluesky-options-text-value="" data-bluesky-options-author-handle-value="practicallybetter.bsky.social" data-bluesky-options-author-did-value="did:plc:jwxd2axqquyd5qlcikd6hesz" data-bluesky-options-muted-value="false" data-bluesky-options-blocking-uri-value="" data-bluesky-options-own-value="false" data-bluesky-options-delete-url-value="" data-bluesky-options-post-element-selector-value='[data-card-type="bsky-post"]'> <button type="button" class="inline-flex items-center" data-action="click->bluesky-options#toggleMenu" aria-label="Post options"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="1"/><circle cx="19" cy="12" r="1"/><circle cx="5" cy="12" r="1"/></svg> </button> <div class="hidden absolute right-0 bottom-full mb-3 w-60 rounded-2xl border border-white/10 bg-[#1C2333] text-white shadow-xl overflow-hidden" data-bluesky-options-target="menu"> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-options#translate"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 4h16v16H4z"/><path d="M9 8h6"/><path d="M9 12h6"/><path d="M9 16h6"/></svg> </span> <span>Translate</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-options#copyText"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="8" y="8" width="12" height="12" rx="2"/><path d="M16 8V6a2 2 0 0 0-2-2h-8a2 2 0 0 0-2 2v8"/></svg> </span> <span>Copy post text</span> </button> <div class="border-t border-white/10"></div> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-options#muteAccount"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 9v6h3l5 5V4L7 9H4z"/><line x1="16" y1="9" x2="19" y2="12"/><line x1="19" y1="12" x2="16" y2="15"/></svg> </span> <span data-bluesky-options-target="muteLabel">Mute account</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-options#blockAccount"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 3h18v18H3z"/><path d="M3 3l18 18"/></svg> </span> <span data-bluesky-options-target="blockLabel">Block account</span> </button> </div> </div> </div> </div> </div> </div> </div> </div> <script> // Prevent navigation when clicking in avatar column area - must run in capture phase before global handler // Only initialize once to avoid duplicate listeners if (!window._avatarColumnNoNavInitialized) { window._avatarColumnNoNavInitialized = true; document.addEventListener('click', function(ev) { try { // Check if target itself has the class OR is inside an element with that class var avatarColumn = (ev.target.classList && ev.target.classList.contains('avatar-column-no-nav')) || (ev.target.closest && ev.target.closest('.avatar-column-no-nav')); if (avatarColumn) { // Only allow navigation if clicking directly on the avatar link itself var isAvatarLink = ev.target.tagName === 'A' && ev.target.href && ev.target.href.indexOf('/author') !== -1; if (!isAvatarLink) { ev.stopPropagation(); ev.stopImmediatePropagation(); ev.preventDefault(); return false; } } } catch(e) {} }, true); // Capture phase - runs BEFORE other handlers } </script> <div class="w-full border-y sm:border bg-white dark:bg-[#0C1220] bluesky-list-card digest-card card-clickable cursor-pointer group" data-href="/bsky/practicallybetter.bsky.social/post/3lgqforrwks2k" role="link" tabindex="0" data-card-type="bsky-post" onclick="if(!event.target.closest('.no-card-link')){ window.location = this.dataset.href }" onkeydown="if((event.key==='Enter' || event.key===' ') && !event.target.closest('.no-card-link')){ window.location = this.dataset.href }"> <div class="px-4 py-3"> <div class="flex items-start gap-4"> <div class="relative w-10 self-stretch flex justify-center no-card-link avatar-column-no-nav" style="min-height:40px; align-self:stretch" onclick="event.stopPropagation(); event.stopImmediatePropagation(); return false;" onkeydown="if(event.key==='Enter' || event.key===' '){ event.stopPropagation(); event.stopImmediatePropagation(); return false; }"> <a href="/author?bsky_handle=practicallybetter.bsky.social" class="no-card-link inline-block flex-shrink-0" aria-label="Practical Betterments" style="align-self: flex-start;"> <img src="https://cdn.bsky.app/img/avatar/plain/did:plc:jwxd2axqquyd5qlcikd6hesz/bafkreifuam6bjsq4c4loo6qtqznl5yhmpw3ij72xixli6pytuabiffhg44@jpeg" alt="practicallybetter.bsky.social" class="w-10 h-10 rounded-full relative z-10" loading="lazy"> </a> </div> <div class="flex-1 min-w-0 -mt-0.5"> <div> <div class="text-[1.1rem] sm:text-[1.15rem] font-semibold text-black flex items-center gap-1"> <a href="/author?bsky_handle=practicallybetter.bsky.social" class="truncate hover:underline text-black no-card-link">Practical Betterments</a> </div> <div class="text-gray-500 text-sm leading-4 -mt-0.5 truncate"> <a href="/author?bsky_handle=practicallybetter.bsky.social" class="hover:underline text-gray-500 no-card-link">@practicallybetter.bsky.social</a> </div> </div> <div class="mt-3 text-[1.2rem] leading-7 break-words text-gray-800 w-[calc(100%+3.5rem)] -ml-[3.5rem]"></div> <a href="https://practicalbetterments.com/sort-out-your-phone-notifications/" target="_blank" rel="noopener" class="block mt-2 border rounded overflow-hidden w-[calc(100%+3.5rem)] -ml-[3.5rem] no-card-link"> <img src="https://cdn.bsky.app/img/feed_thumbnail/plain/did:plc:jwxd2axqquyd5qlcikd6hesz/bafkreiavdsqwelbb3vxee2isz53li7itycbc4vzqgnostgxkx6pl54wlsi@jpeg" class="w-full h-40 object-cover" loading="lazy"> <div class="p-2"> <div class="text-sm font-semibold truncate">Sort out your phone notifications</div> <div class="text-xs text-gray-500 truncate">Take back time, attention, and a modicum of agency from our techno overlords. Sort out your phone notifications</div> </div> <div class="border-t px-2 py-2 text-sm text-gray-600 flex items-center gap-2"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M2 12h20"/><path d="M12 2a15.3 15.3 0 0 1 0 20"/><path d="M12 2a15.3 15.3 0 0 0 0 20"/></svg> <span class="truncate">practicalbetterments.com</span> </div> </a> <div class="mt-3 text-xs text-gray-500 flex items-center gap-2 whitespace-nowrap overflow-hidden w-[calc(100%+3.5rem)] -ml-[3.5rem]"> <span>January 27, 2025 at 4:53 PM</span> </div> <div class="border-t my-2 w-[calc(100%+3.5rem)] -ml-[3.5rem]"></div> <div class="mt-3 flex items-center justify-between text-gray-600 text-sm w-[calc(100%+3.5rem)] -ml-[3.5rem] no-card-link" data-controller="bluesky-interactions"> <div class="flex items-center justify-between w-[300px] pr-4 no-card-link"> <div class="hidden" data-post-text-uri="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lgqforrwks2k"> </div> <button type="button" class="flex items-center gap-1 hover:text-black no-card-link" data-action="click->bluesky-auth#requireConnection click->bluesky-interactions#reply" data-bluesky-interactions-reply-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lgqforrwks2k" data-bluesky-interactions-reply-cid-param="bafyreifafsjcukbsoupxsjceqz452jts3i6hdvif6y7yk6fbql5gegohtu" data-bluesky-interactions-reply-root-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lgqforrwks2k" data-bluesky-interactions-reply-root-cid-param="bafyreifafsjcukbsoupxsjceqz452jts3i6hdvif6y7yk6fbql5gegohtu" data-bluesky-interactions-reply-author-name-param="Practical Betterments" data-bluesky-interactions-reply-author-avatar-param="https://cdn.bsky.app/img/avatar/plain/did:plc:jwxd2axqquyd5qlcikd6hesz/bafkreifuam6bjsq4c4loo6qtqznl5yhmpw3ij72xixli6pytuabiffhg44@jpeg" data-bluesky-interactions-post-path-param="/bsky/practicallybetter.bsky.social/post/3lgqforrwks2k" title="Reply" style="pointer-events: auto; cursor: pointer; z-index: 10; position: relative;"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15a4 4 0 0 1-4 4H7l-4 4V7a4 4 0 0 1 4-4h10a4 4 0 0 1 4 4z"/></svg> </button> <div class="relative no-card-link" data-controller="bluesky-repost-menu" data-bluesky-repost-menu-uri-value="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lgqforrwks2k" data-bluesky-repost-menu-cid-value="bafyreifafsjcukbsoupxsjceqz452jts3i6hdvif6y7yk6fbql5gegohtu" data-bluesky-repost-menu-repost-uri-value="" data-bluesky-repost-menu-is-reposted-value="false" data-bluesky-repost-menu-author-handle-value="practicallybetter.bsky.social" data-bluesky-repost-menu-post-text-value="" style="pointer-events:auto; cursor:pointer;"> <button type="button" class="flex items-center gap-1 hover:text-black " data-action="click->bluesky-repost-menu#toggleMenu" data-bluesky-interactions-target="repostButton" title="Repost"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg> </button> <div class="hidden absolute left-0 bottom-full mb-3 w-48 rounded-2xl border border-white/10 bg-[#1C2333] text-white shadow-xl overflow-hidden z-50" data-bluesky-repost-menu-target="menu"> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-repost-menu#repost"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg> <span>Repost</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-repost-menu#quote"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg> <span>Quote post</span> </button> </div> </div> <button type="button" class="flex items-center gap-1 hover:text-black no-card-link " data-action="click->bluesky-auth#requireConnection click->bluesky-interactions#toggleLike" data-bluesky-interactions-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lgqforrwks2k" data-bluesky-interactions-cid-param="bafyreifafsjcukbsoupxsjceqz452jts3i6hdvif6y7yk6fbql5gegohtu" data-bluesky-interactions-like-uri-param="" data-bluesky-interactions-target="likeButton" title="Like"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 1 0-7.78 7.78L12 21.23l8.84-8.84a5.5 5.5 0 0 0 0-7.78z"/></svg> <span data-bluesky-interactions-target="likeCount">2</span> </button> </div> <div class="flex items-center gap-4 text-gray-500"> <button type="button" class="flex items-center hover:text-black no-card-link" data-controller="share" data-share-url-value="https://oauth.lightnews.app/bsky/practicallybetter.bsky.social/post/3lgqforrwks2k" data-share-title-value="Practical Betterments on Lightnews" data-share-text-value="" data-action="click->share#shareSystem" title="Share" style="pointer-events:auto; cursor:pointer;"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 12v7a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-7"/><polyline points="16 6 12 2 8 6"/><line x1="12" y1="2" x2="12" y2="15"/></svg> </button> <div class="relative no-card-link" data-controller="bluesky-options" data-bluesky-options-text-value="" data-bluesky-options-author-handle-value="practicallybetter.bsky.social" data-bluesky-options-author-did-value="did:plc:jwxd2axqquyd5qlcikd6hesz" data-bluesky-options-muted-value="false" data-bluesky-options-blocking-uri-value="" data-bluesky-options-own-value="false" data-bluesky-options-delete-url-value="" data-bluesky-options-post-element-selector-value='[data-card-type="bsky-post"]'> <button type="button" class="inline-flex items-center" data-action="click->bluesky-options#toggleMenu" aria-label="Post options"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="1"/><circle cx="19" cy="12" r="1"/><circle cx="5" cy="12" r="1"/></svg> </button> <div class="hidden absolute right-0 bottom-full mb-3 w-60 rounded-2xl border border-white/10 bg-[#1C2333] text-white shadow-xl overflow-hidden" data-bluesky-options-target="menu"> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-options#translate"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 4h16v16H4z"/><path d="M9 8h6"/><path d="M9 12h6"/><path d="M9 16h6"/></svg> </span> <span>Translate</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-options#copyText"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="8" y="8" width="12" height="12" rx="2"/><path d="M16 8V6a2 2 0 0 0-2-2h-8a2 2 0 0 0-2 2v8"/></svg> </span> <span>Copy post text</span> </button> <div class="border-t border-white/10"></div> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-options#muteAccount"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 9v6h3l5 5V4L7 9H4z"/><line x1="16" y1="9" x2="19" y2="12"/><line x1="19" y1="12" x2="16" y2="15"/></svg> </span> <span data-bluesky-options-target="muteLabel">Mute account</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-options#blockAccount"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 3h18v18H3z"/><path d="M3 3l18 18"/></svg> </span> <span data-bluesky-options-target="blockLabel">Block account</span> </button> </div> </div> </div> </div> </div> </div> </div> </div> <script> // Prevent navigation when clicking in avatar column area - must run in capture phase before global handler // Only initialize once to avoid duplicate listeners if (!window._avatarColumnNoNavInitialized) { window._avatarColumnNoNavInitialized = true; document.addEventListener('click', function(ev) { try { // Check if target itself has the class OR is inside an element with that class var avatarColumn = (ev.target.classList && ev.target.classList.contains('avatar-column-no-nav')) || (ev.target.closest && ev.target.closest('.avatar-column-no-nav')); if (avatarColumn) { // Only allow navigation if clicking directly on the avatar link itself var isAvatarLink = ev.target.tagName === 'A' && ev.target.href && ev.target.href.indexOf('/author') !== -1; if (!isAvatarLink) { ev.stopPropagation(); ev.stopImmediatePropagation(); ev.preventDefault(); return false; } } } catch(e) {} }, true); // Capture phase - runs BEFORE other handlers } </script> <div class="w-full border-y sm:border bg-white dark:bg-[#0C1220] bluesky-list-card digest-card card-clickable cursor-pointer group" data-href="/bsky/practicallybetter.bsky.social/post/3lg6i5ckpas2f" role="link" tabindex="0" data-card-type="bsky-post" onclick="if(!event.target.closest('.no-card-link')){ window.location = this.dataset.href }" onkeydown="if((event.key==='Enter' || event.key===' ') && !event.target.closest('.no-card-link')){ window.location = this.dataset.href }"> <div class="px-4 py-3"> <div class="flex items-start gap-4"> <div class="relative w-10 self-stretch flex justify-center no-card-link avatar-column-no-nav" style="min-height:40px; align-self:stretch" onclick="event.stopPropagation(); event.stopImmediatePropagation(); return false;" onkeydown="if(event.key==='Enter' || event.key===' '){ event.stopPropagation(); event.stopImmediatePropagation(); return false; }"> <a href="/author?bsky_handle=practicallybetter.bsky.social" class="no-card-link inline-block flex-shrink-0" aria-label="Practical Betterments" style="align-self: flex-start;"> <img src="https://cdn.bsky.app/img/avatar/plain/did:plc:jwxd2axqquyd5qlcikd6hesz/bafkreifuam6bjsq4c4loo6qtqznl5yhmpw3ij72xixli6pytuabiffhg44@jpeg" alt="practicallybetter.bsky.social" class="w-10 h-10 rounded-full relative z-10" loading="lazy"> </a> </div> <div class="flex-1 min-w-0 -mt-0.5"> <div> <div class="text-[1.1rem] sm:text-[1.15rem] font-semibold text-black flex items-center gap-1"> <a href="/author?bsky_handle=practicallybetter.bsky.social" class="truncate hover:underline text-black no-card-link">Practical Betterments</a> </div> <div class="text-gray-500 text-sm leading-4 -mt-0.5 truncate"> <a href="/author?bsky_handle=practicallybetter.bsky.social" class="hover:underline text-gray-500 no-card-link">@practicallybetter.bsky.social</a> </div> </div> <div class="mt-3 text-[1.2rem] leading-7 break-words text-gray-800 w-[calc(100%+3.5rem)] -ml-[3.5rem]"></div> <a href="https://practicalbetterments.com/add-mundane-non-password-info-to-your-password-manager/" target="_blank" rel="noopener" class="block mt-2 border rounded overflow-hidden w-[calc(100%+3.5rem)] -ml-[3.5rem] no-card-link"> <img src="https://cdn.bsky.app/img/feed_thumbnail/plain/did:plc:jwxd2axqquyd5qlcikd6hesz/bafkreiacqmbsiban4jchqbornc7cqxbt2raibqtzply6plxl2grjlyrx74@jpeg" class="w-full h-40 object-cover" loading="lazy"> <div class="p-2"> <div class="text-sm font-semibold truncate">Add mundane non-password info to your password manager</div> <div class="text-xs text-gray-500 truncate">Don't waste any more of yours searching mechanically through strings of digits—that is what computers are for.</div> </div> <div class="border-t px-2 py-2 text-sm text-gray-600 flex items-center gap-2"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M2 12h20"/><path d="M12 2a15.3 15.3 0 0 1 0 20"/><path d="M12 2a15.3 15.3 0 0 0 0 20"/></svg> <span class="truncate">practicalbetterments.com</span> </div> </a> <div class="mt-3 text-xs text-gray-500 flex items-center gap-2 whitespace-nowrap overflow-hidden w-[calc(100%+3.5rem)] -ml-[3.5rem]"> <span>January 20, 2025 at 1:49 PM</span> </div> <div class="border-t my-2 w-[calc(100%+3.5rem)] -ml-[3.5rem]"></div> <div class="mt-3 flex items-center justify-between text-gray-600 text-sm w-[calc(100%+3.5rem)] -ml-[3.5rem] no-card-link" data-controller="bluesky-interactions"> <div class="flex items-center justify-between w-[300px] pr-4 no-card-link"> <div class="hidden" data-post-text-uri="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lg6i5ckpas2f"> </div> <button type="button" class="flex items-center gap-1 hover:text-black no-card-link" data-action="click->bluesky-auth#requireConnection click->bluesky-interactions#reply" data-bluesky-interactions-reply-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lg6i5ckpas2f" data-bluesky-interactions-reply-cid-param="bafyreihcbnz4n54x6qayxa56wmwr7ggzupzdanftumrx4uluhbf5aioarm" data-bluesky-interactions-reply-root-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lg6i5ckpas2f" data-bluesky-interactions-reply-root-cid-param="bafyreihcbnz4n54x6qayxa56wmwr7ggzupzdanftumrx4uluhbf5aioarm" data-bluesky-interactions-reply-author-name-param="Practical Betterments" data-bluesky-interactions-reply-author-avatar-param="https://cdn.bsky.app/img/avatar/plain/did:plc:jwxd2axqquyd5qlcikd6hesz/bafkreifuam6bjsq4c4loo6qtqznl5yhmpw3ij72xixli6pytuabiffhg44@jpeg" data-bluesky-interactions-post-path-param="/bsky/practicallybetter.bsky.social/post/3lg6i5ckpas2f" title="Reply" style="pointer-events: auto; cursor: pointer; z-index: 10; position: relative;"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15a4 4 0 0 1-4 4H7l-4 4V7a4 4 0 0 1 4-4h10a4 4 0 0 1 4 4z"/></svg> </button> <div class="relative no-card-link" data-controller="bluesky-repost-menu" data-bluesky-repost-menu-uri-value="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lg6i5ckpas2f" data-bluesky-repost-menu-cid-value="bafyreihcbnz4n54x6qayxa56wmwr7ggzupzdanftumrx4uluhbf5aioarm" data-bluesky-repost-menu-repost-uri-value="" data-bluesky-repost-menu-is-reposted-value="false" data-bluesky-repost-menu-author-handle-value="practicallybetter.bsky.social" data-bluesky-repost-menu-post-text-value="" style="pointer-events:auto; cursor:pointer;"> <button type="button" class="flex items-center gap-1 hover:text-black " data-action="click->bluesky-repost-menu#toggleMenu" data-bluesky-interactions-target="repostButton" title="Repost"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg> </button> <div class="hidden absolute left-0 bottom-full mb-3 w-48 rounded-2xl border border-white/10 bg-[#1C2333] text-white shadow-xl overflow-hidden z-50" data-bluesky-repost-menu-target="menu"> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-repost-menu#repost"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg> <span>Repost</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-repost-menu#quote"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg> <span>Quote post</span> </button> </div> </div> <button type="button" class="flex items-center gap-1 hover:text-black no-card-link " data-action="click->bluesky-auth#requireConnection click->bluesky-interactions#toggleLike" data-bluesky-interactions-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lg6i5ckpas2f" data-bluesky-interactions-cid-param="bafyreihcbnz4n54x6qayxa56wmwr7ggzupzdanftumrx4uluhbf5aioarm" data-bluesky-interactions-like-uri-param="" data-bluesky-interactions-target="likeButton" title="Like"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 1 0-7.78 7.78L12 21.23l8.84-8.84a5.5 5.5 0 0 0 0-7.78z"/></svg> <span data-bluesky-interactions-target="likeCount">2</span> </button> </div> <div class="flex items-center gap-4 text-gray-500"> <button type="button" class="flex items-center hover:text-black no-card-link" data-controller="share" data-share-url-value="https://oauth.lightnews.app/bsky/practicallybetter.bsky.social/post/3lg6i5ckpas2f" data-share-title-value="Practical Betterments on Lightnews" data-share-text-value="" data-action="click->share#shareSystem" title="Share" style="pointer-events:auto; cursor:pointer;"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 12v7a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-7"/><polyline points="16 6 12 2 8 6"/><line x1="12" y1="2" x2="12" y2="15"/></svg> </button> <div class="relative no-card-link" data-controller="bluesky-options" data-bluesky-options-text-value="" data-bluesky-options-author-handle-value="practicallybetter.bsky.social" data-bluesky-options-author-did-value="did:plc:jwxd2axqquyd5qlcikd6hesz" data-bluesky-options-muted-value="false" data-bluesky-options-blocking-uri-value="" data-bluesky-options-own-value="false" data-bluesky-options-delete-url-value="" data-bluesky-options-post-element-selector-value='[data-card-type="bsky-post"]'> <button type="button" class="inline-flex items-center" data-action="click->bluesky-options#toggleMenu" aria-label="Post options"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="1"/><circle cx="19" cy="12" r="1"/><circle cx="5" cy="12" r="1"/></svg> </button> <div class="hidden absolute right-0 bottom-full mb-3 w-60 rounded-2xl border border-white/10 bg-[#1C2333] text-white shadow-xl overflow-hidden" data-bluesky-options-target="menu"> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-options#translate"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 4h16v16H4z"/><path d="M9 8h6"/><path d="M9 12h6"/><path d="M9 16h6"/></svg> </span> <span>Translate</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-options#copyText"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="8" y="8" width="12" height="12" rx="2"/><path d="M16 8V6a2 2 0 0 0-2-2h-8a2 2 0 0 0-2 2v8"/></svg> </span> <span>Copy post text</span> </button> <div class="border-t border-white/10"></div> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-options#muteAccount"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 9v6h3l5 5V4L7 9H4z"/><line x1="16" y1="9" x2="19" y2="12"/><line x1="19" y1="12" x2="16" y2="15"/></svg> </span> <span data-bluesky-options-target="muteLabel">Mute account</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-options#blockAccount"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 3h18v18H3z"/><path d="M3 3l18 18"/></svg> </span> <span data-bluesky-options-target="blockLabel">Block account</span> </button> </div> </div> </div> </div> </div> </div> </div> </div> <script> // Prevent navigation when clicking in avatar column area - must run in capture phase before global handler // Only initialize once to avoid duplicate listeners if (!window._avatarColumnNoNavInitialized) { window._avatarColumnNoNavInitialized = true; document.addEventListener('click', function(ev) { try { // Check if target itself has the class OR is inside an element with that class var avatarColumn = (ev.target.classList && ev.target.classList.contains('avatar-column-no-nav')) || (ev.target.closest && ev.target.closest('.avatar-column-no-nav')); if (avatarColumn) { // Only allow navigation if clicking directly on the avatar link itself var isAvatarLink = ev.target.tagName === 'A' && ev.target.href && ev.target.href.indexOf('/author') !== -1; if (!isAvatarLink) { ev.stopPropagation(); ev.stopImmediatePropagation(); ev.preventDefault(); return false; } } } catch(e) {} }, true); // Capture phase - runs BEFORE other handlers } </script> <div class="w-full border-y sm:border bg-white dark:bg-[#0C1220] bluesky-list-card digest-card card-clickable cursor-pointer group" data-href="/bsky/practicallybetter.bsky.social/post/3lfsjgpodoc2w" role="link" tabindex="0" data-card-type="bsky-post" onclick="if(!event.target.closest('.no-card-link')){ window.location = this.dataset.href }" onkeydown="if((event.key==='Enter' || event.key===' ') && !event.target.closest('.no-card-link')){ window.location = this.dataset.href }"> <div class="px-4 py-3"> <div class="flex items-start gap-4"> <div class="relative w-10 self-stretch flex justify-center no-card-link avatar-column-no-nav" style="min-height:40px; align-self:stretch" onclick="event.stopPropagation(); event.stopImmediatePropagation(); return false;" onkeydown="if(event.key==='Enter' || event.key===' '){ event.stopPropagation(); event.stopImmediatePropagation(); return false; }"> <a href="/author?bsky_handle=practicallybetter.bsky.social" class="no-card-link inline-block flex-shrink-0" aria-label="Practical Betterments" style="align-self: flex-start;"> <img src="https://cdn.bsky.app/img/avatar/plain/did:plc:jwxd2axqquyd5qlcikd6hesz/bafkreifuam6bjsq4c4loo6qtqznl5yhmpw3ij72xixli6pytuabiffhg44@jpeg" alt="practicallybetter.bsky.social" class="w-10 h-10 rounded-full relative z-10" loading="lazy"> </a> </div> <div class="flex-1 min-w-0 -mt-0.5"> <div> <div class="text-[1.1rem] sm:text-[1.15rem] font-semibold text-black flex items-center gap-1"> <a href="/author?bsky_handle=practicallybetter.bsky.social" class="truncate hover:underline text-black no-card-link">Practical Betterments</a> </div> <div class="text-gray-500 text-sm leading-4 -mt-0.5 truncate"> <a href="/author?bsky_handle=practicallybetter.bsky.social" class="hover:underline text-gray-500 no-card-link">@practicallybetter.bsky.social</a> </div> </div> <div class="mt-3 text-[1.2rem] leading-7 break-words text-gray-800 w-[calc(100%+3.5rem)] -ml-[3.5rem]"></div> <a href="https://practicalbetterments.com/cut-rounded-corners-into-documents/" target="_blank" rel="noopener" class="block mt-2 border rounded overflow-hidden w-[calc(100%+3.5rem)] -ml-[3.5rem] no-card-link"> <img src="https://cdn.bsky.app/img/feed_thumbnail/plain/did:plc:jwxd2axqquyd5qlcikd6hesz/bafkreidj5wuk3zetv3kdcyjouiqpytwse5gsd46agemlnfhxdm2jliouya@jpeg" class="w-full h-40 object-cover" loading="lazy"> <div class="p-2"> <div class="text-sm font-semibold truncate">Cut rounded corners into your documents</div> <div class="text-xs text-gray-500 truncate">Cutting corners saves you weight and reduces the chance of pointy paper accidents</div> </div> <div class="border-t px-2 py-2 text-sm text-gray-600 flex items-center gap-2"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M2 12h20"/><path d="M12 2a15.3 15.3 0 0 1 0 20"/><path d="M12 2a15.3 15.3 0 0 0 0 20"/></svg> <span class="truncate">practicalbetterments.com</span> </div> </a> <div class="mt-3 text-xs text-gray-500 flex items-center gap-2 whitespace-nowrap overflow-hidden w-[calc(100%+3.5rem)] -ml-[3.5rem]"> <span>January 15, 2025 at 7:40 PM</span> </div> <div class="border-t my-2 w-[calc(100%+3.5rem)] -ml-[3.5rem]"></div> <div class="mt-3 flex items-center justify-between text-gray-600 text-sm w-[calc(100%+3.5rem)] -ml-[3.5rem] no-card-link" data-controller="bluesky-interactions"> <div class="flex items-center justify-between w-[300px] pr-4 no-card-link"> <div class="hidden" data-post-text-uri="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lfsjgpodoc2w"> </div> <button type="button" class="flex items-center gap-1 hover:text-black no-card-link" data-action="click->bluesky-auth#requireConnection click->bluesky-interactions#reply" data-bluesky-interactions-reply-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lfsjgpodoc2w" data-bluesky-interactions-reply-cid-param="bafyreig2yfakng64krhf5efinuik5zx7kqgerryg3htlwxyveuophrrf5y" data-bluesky-interactions-reply-root-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lfsjgpodoc2w" data-bluesky-interactions-reply-root-cid-param="bafyreig2yfakng64krhf5efinuik5zx7kqgerryg3htlwxyveuophrrf5y" data-bluesky-interactions-reply-author-name-param="Practical Betterments" data-bluesky-interactions-reply-author-avatar-param="https://cdn.bsky.app/img/avatar/plain/did:plc:jwxd2axqquyd5qlcikd6hesz/bafkreifuam6bjsq4c4loo6qtqznl5yhmpw3ij72xixli6pytuabiffhg44@jpeg" data-bluesky-interactions-post-path-param="/bsky/practicallybetter.bsky.social/post/3lfsjgpodoc2w" title="Reply" style="pointer-events: auto; cursor: pointer; z-index: 10; position: relative;"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15a4 4 0 0 1-4 4H7l-4 4V7a4 4 0 0 1 4-4h10a4 4 0 0 1 4 4z"/></svg> </button> <div class="relative no-card-link" data-controller="bluesky-repost-menu" data-bluesky-repost-menu-uri-value="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lfsjgpodoc2w" data-bluesky-repost-menu-cid-value="bafyreig2yfakng64krhf5efinuik5zx7kqgerryg3htlwxyveuophrrf5y" data-bluesky-repost-menu-repost-uri-value="" data-bluesky-repost-menu-is-reposted-value="false" data-bluesky-repost-menu-author-handle-value="practicallybetter.bsky.social" data-bluesky-repost-menu-post-text-value="" style="pointer-events:auto; cursor:pointer;"> <button type="button" class="flex items-center gap-1 hover:text-black " data-action="click->bluesky-repost-menu#toggleMenu" data-bluesky-interactions-target="repostButton" title="Repost"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg> </button> <div class="hidden absolute left-0 bottom-full mb-3 w-48 rounded-2xl border border-white/10 bg-[#1C2333] text-white shadow-xl overflow-hidden z-50" data-bluesky-repost-menu-target="menu"> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-repost-menu#repost"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg> <span>Repost</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-repost-menu#quote"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg> <span>Quote post</span> </button> </div> </div> <button type="button" class="flex items-center gap-1 hover:text-black no-card-link " data-action="click->bluesky-auth#requireConnection click->bluesky-interactions#toggleLike" data-bluesky-interactions-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lfsjgpodoc2w" data-bluesky-interactions-cid-param="bafyreig2yfakng64krhf5efinuik5zx7kqgerryg3htlwxyveuophrrf5y" data-bluesky-interactions-like-uri-param="" data-bluesky-interactions-target="likeButton" title="Like"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 1 0-7.78 7.78L12 21.23l8.84-8.84a5.5 5.5 0 0 0 0-7.78z"/></svg> <span data-bluesky-interactions-target="likeCount">2</span> </button> </div> <div class="flex items-center gap-4 text-gray-500"> <button type="button" class="flex items-center hover:text-black no-card-link" data-controller="share" data-share-url-value="https://oauth.lightnews.app/bsky/practicallybetter.bsky.social/post/3lfsjgpodoc2w" data-share-title-value="Practical Betterments on Lightnews" data-share-text-value="" data-action="click->share#shareSystem" title="Share" style="pointer-events:auto; cursor:pointer;"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 12v7a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-7"/><polyline points="16 6 12 2 8 6"/><line x1="12" y1="2" x2="12" y2="15"/></svg> </button> <div class="relative no-card-link" data-controller="bluesky-options" data-bluesky-options-text-value="" data-bluesky-options-author-handle-value="practicallybetter.bsky.social" data-bluesky-options-author-did-value="did:plc:jwxd2axqquyd5qlcikd6hesz" data-bluesky-options-muted-value="false" data-bluesky-options-blocking-uri-value="" data-bluesky-options-own-value="false" data-bluesky-options-delete-url-value="" data-bluesky-options-post-element-selector-value='[data-card-type="bsky-post"]'> <button type="button" class="inline-flex items-center" data-action="click->bluesky-options#toggleMenu" aria-label="Post options"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="1"/><circle cx="19" cy="12" r="1"/><circle cx="5" cy="12" r="1"/></svg> </button> <div class="hidden absolute right-0 bottom-full mb-3 w-60 rounded-2xl border border-white/10 bg-[#1C2333] text-white shadow-xl overflow-hidden" data-bluesky-options-target="menu"> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-options#translate"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 4h16v16H4z"/><path d="M9 8h6"/><path d="M9 12h6"/><path d="M9 16h6"/></svg> </span> <span>Translate</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-options#copyText"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="8" y="8" width="12" height="12" rx="2"/><path d="M16 8V6a2 2 0 0 0-2-2h-8a2 2 0 0 0-2 2v8"/></svg> </span> <span>Copy post text</span> </button> <div class="border-t border-white/10"></div> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-options#muteAccount"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 9v6h3l5 5V4L7 9H4z"/><line x1="16" y1="9" x2="19" y2="12"/><line x1="19" y1="12" x2="16" y2="15"/></svg> </span> <span data-bluesky-options-target="muteLabel">Mute account</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-options#blockAccount"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 3h18v18H3z"/><path d="M3 3l18 18"/></svg> </span> <span data-bluesky-options-target="blockLabel">Block account</span> </button> </div> </div> </div> </div> </div> </div> </div> </div> <script> // Prevent navigation when clicking in avatar column area - must run in capture phase before global handler // Only initialize once to avoid duplicate listeners if (!window._avatarColumnNoNavInitialized) { window._avatarColumnNoNavInitialized = true; document.addEventListener('click', function(ev) { try { // Check if target itself has the class OR is inside an element with that class var avatarColumn = (ev.target.classList && ev.target.classList.contains('avatar-column-no-nav')) || (ev.target.closest && ev.target.closest('.avatar-column-no-nav')); if (avatarColumn) { // Only allow navigation if clicking directly on the avatar link itself var isAvatarLink = ev.target.tagName === 'A' && ev.target.href && ev.target.href.indexOf('/author') !== -1; if (!isAvatarLink) { ev.stopPropagation(); ev.stopImmediatePropagation(); ev.preventDefault(); return false; } } } catch(e) {} }, true); // Capture phase - runs BEFORE other handlers } </script> <div class="w-full border-y sm:border bg-white dark:bg-[#0C1220] bluesky-list-card digest-card card-clickable cursor-pointer group" data-href="/bsky/practicallybetter.bsky.social/post/3lfn5b4blck2c" role="link" tabindex="0" data-card-type="bsky-post" onclick="if(!event.target.closest('.no-card-link')){ window.location = this.dataset.href }" onkeydown="if((event.key==='Enter' || event.key===' ') && !event.target.closest('.no-card-link')){ window.location = this.dataset.href }"> <div class="px-4 py-3"> <div class="flex items-start gap-4"> <div class="relative w-10 self-stretch flex justify-center no-card-link avatar-column-no-nav" style="min-height:40px; align-self:stretch" onclick="event.stopPropagation(); event.stopImmediatePropagation(); return false;" onkeydown="if(event.key==='Enter' || event.key===' '){ event.stopPropagation(); event.stopImmediatePropagation(); return false; }"> <a href="/author?bsky_handle=practicallybetter.bsky.social" class="no-card-link inline-block flex-shrink-0" aria-label="Practical Betterments" style="align-self: flex-start;"> <img src="https://cdn.bsky.app/img/avatar/plain/did:plc:jwxd2axqquyd5qlcikd6hesz/bafkreifuam6bjsq4c4loo6qtqznl5yhmpw3ij72xixli6pytuabiffhg44@jpeg" alt="practicallybetter.bsky.social" class="w-10 h-10 rounded-full relative z-10" loading="lazy"> </a> </div> <div class="flex-1 min-w-0 -mt-0.5"> <div> <div class="text-[1.1rem] sm:text-[1.15rem] font-semibold text-black flex items-center gap-1"> <a href="/author?bsky_handle=practicallybetter.bsky.social" class="truncate hover:underline text-black no-card-link">Practical Betterments</a> </div> <div class="text-gray-500 text-sm leading-4 -mt-0.5 truncate"> <a href="/author?bsky_handle=practicallybetter.bsky.social" class="hover:underline text-gray-500 no-card-link">@practicallybetter.bsky.social</a> </div> </div> <div class="mt-3 text-[1.2rem] leading-7 break-words text-gray-800 w-[calc(100%+3.5rem)] -ml-[3.5rem]"></div> <a href="https://practicalbetterments.com/enable-sticky-keys/" target="_blank" rel="noopener" class="block mt-2 border rounded overflow-hidden w-[calc(100%+3.5rem)] -ml-[3.5rem] no-card-link"> <img src="https://cdn.bsky.app/img/feed_thumbnail/plain/did:plc:jwxd2axqquyd5qlcikd6hesz/bafkreickk3fht5rjor3fkf7eqchdolmsjenutdu4g2kfdgpvx3hdfinsva@jpeg" class="w-full h-40 object-cover" loading="lazy"> <div class="p-2"> <div class="text-sm font-semibold truncate">Enable sticky keys on your computer</div> <div class="text-xs text-gray-500 truncate">You can reduce the strain on your pinky fingers and shave nanoseconds off your typing speed by enabling sticky keys.</div> </div> <div class="border-t px-2 py-2 text-sm text-gray-600 flex items-center gap-2"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M2 12h20"/><path d="M12 2a15.3 15.3 0 0 1 0 20"/><path d="M12 2a15.3 15.3 0 0 0 0 20"/></svg> <span class="truncate">practicalbetterments.com</span> </div> </a> <div class="mt-3 text-xs text-gray-500 flex items-center gap-2 whitespace-nowrap overflow-hidden w-[calc(100%+3.5rem)] -ml-[3.5rem]"> <span>January 13, 2025 at 4:19 PM</span> </div> <div class="border-t my-2 w-[calc(100%+3.5rem)] -ml-[3.5rem]"></div> <div class="mt-3 flex items-center justify-between text-gray-600 text-sm w-[calc(100%+3.5rem)] -ml-[3.5rem] no-card-link" data-controller="bluesky-interactions"> <div class="flex items-center justify-between w-[300px] pr-4 no-card-link"> <div class="hidden" data-post-text-uri="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lfn5b4blck2c"> </div> <button type="button" class="flex items-center gap-1 hover:text-black no-card-link" data-action="click->bluesky-auth#requireConnection click->bluesky-interactions#reply" data-bluesky-interactions-reply-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lfn5b4blck2c" data-bluesky-interactions-reply-cid-param="bafyreig2kk6qlx4pha6i5dtlpmdmmsgbxoqo5h6sdpu6nw4lxfk533utn4" data-bluesky-interactions-reply-root-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lfn5b4blck2c" data-bluesky-interactions-reply-root-cid-param="bafyreig2kk6qlx4pha6i5dtlpmdmmsgbxoqo5h6sdpu6nw4lxfk533utn4" data-bluesky-interactions-reply-author-name-param="Practical Betterments" data-bluesky-interactions-reply-author-avatar-param="https://cdn.bsky.app/img/avatar/plain/did:plc:jwxd2axqquyd5qlcikd6hesz/bafkreifuam6bjsq4c4loo6qtqznl5yhmpw3ij72xixli6pytuabiffhg44@jpeg" data-bluesky-interactions-post-path-param="/bsky/practicallybetter.bsky.social/post/3lfn5b4blck2c" title="Reply" style="pointer-events: auto; cursor: pointer; z-index: 10; position: relative;"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15a4 4 0 0 1-4 4H7l-4 4V7a4 4 0 0 1 4-4h10a4 4 0 0 1 4 4z"/></svg> </button> <div class="relative no-card-link" data-controller="bluesky-repost-menu" data-bluesky-repost-menu-uri-value="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lfn5b4blck2c" data-bluesky-repost-menu-cid-value="bafyreig2kk6qlx4pha6i5dtlpmdmmsgbxoqo5h6sdpu6nw4lxfk533utn4" data-bluesky-repost-menu-repost-uri-value="" data-bluesky-repost-menu-is-reposted-value="false" data-bluesky-repost-menu-author-handle-value="practicallybetter.bsky.social" data-bluesky-repost-menu-post-text-value="" style="pointer-events:auto; cursor:pointer;"> <button type="button" class="flex items-center gap-1 hover:text-black " data-action="click->bluesky-repost-menu#toggleMenu" data-bluesky-interactions-target="repostButton" title="Repost"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg> </button> <div class="hidden absolute left-0 bottom-full mb-3 w-48 rounded-2xl border border-white/10 bg-[#1C2333] text-white shadow-xl overflow-hidden z-50" data-bluesky-repost-menu-target="menu"> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-repost-menu#repost"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg> <span>Repost</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-repost-menu#quote"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg> <span>Quote post</span> </button> </div> </div> <button type="button" class="flex items-center gap-1 hover:text-black no-card-link " data-action="click->bluesky-auth#requireConnection click->bluesky-interactions#toggleLike" data-bluesky-interactions-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lfn5b4blck2c" data-bluesky-interactions-cid-param="bafyreig2kk6qlx4pha6i5dtlpmdmmsgbxoqo5h6sdpu6nw4lxfk533utn4" data-bluesky-interactions-like-uri-param="" data-bluesky-interactions-target="likeButton" title="Like"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 1 0-7.78 7.78L12 21.23l8.84-8.84a5.5 5.5 0 0 0 0-7.78z"/></svg> <span data-bluesky-interactions-target="likeCount">1</span> </button> </div> <div class="flex items-center gap-4 text-gray-500"> <button type="button" class="flex items-center hover:text-black no-card-link" data-controller="share" data-share-url-value="https://oauth.lightnews.app/bsky/practicallybetter.bsky.social/post/3lfn5b4blck2c" data-share-title-value="Practical Betterments on Lightnews" data-share-text-value="" data-action="click->share#shareSystem" title="Share" style="pointer-events:auto; cursor:pointer;"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 12v7a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-7"/><polyline points="16 6 12 2 8 6"/><line x1="12" y1="2" x2="12" y2="15"/></svg> </button> <div class="relative no-card-link" data-controller="bluesky-options" data-bluesky-options-text-value="" data-bluesky-options-author-handle-value="practicallybetter.bsky.social" data-bluesky-options-author-did-value="did:plc:jwxd2axqquyd5qlcikd6hesz" data-bluesky-options-muted-value="false" data-bluesky-options-blocking-uri-value="" data-bluesky-options-own-value="false" data-bluesky-options-delete-url-value="" data-bluesky-options-post-element-selector-value='[data-card-type="bsky-post"]'> <button type="button" class="inline-flex items-center" data-action="click->bluesky-options#toggleMenu" aria-label="Post options"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="1"/><circle cx="19" cy="12" r="1"/><circle cx="5" cy="12" r="1"/></svg> </button> <div class="hidden absolute right-0 bottom-full mb-3 w-60 rounded-2xl border border-white/10 bg-[#1C2333] text-white shadow-xl overflow-hidden" data-bluesky-options-target="menu"> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-options#translate"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 4h16v16H4z"/><path d="M9 8h6"/><path d="M9 12h6"/><path d="M9 16h6"/></svg> </span> <span>Translate</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-options#copyText"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="8" y="8" width="12" height="12" rx="2"/><path d="M16 8V6a2 2 0 0 0-2-2h-8a2 2 0 0 0-2 2v8"/></svg> </span> <span>Copy post text</span> </button> <div class="border-t border-white/10"></div> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-options#muteAccount"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 9v6h3l5 5V4L7 9H4z"/><line x1="16" y1="9" x2="19" y2="12"/><line x1="19" y1="12" x2="16" y2="15"/></svg> </span> <span data-bluesky-options-target="muteLabel">Mute account</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-options#blockAccount"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 3h18v18H3z"/><path d="M3 3l18 18"/></svg> </span> <span data-bluesky-options-target="blockLabel">Block account</span> </button> </div> </div> </div> </div> </div> </div> </div> </div> <script> // Prevent navigation when clicking in avatar column area - must run in capture phase before global handler // Only initialize once to avoid duplicate listeners if (!window._avatarColumnNoNavInitialized) { window._avatarColumnNoNavInitialized = true; document.addEventListener('click', function(ev) { try { // Check if target itself has the class OR is inside an element with that class var avatarColumn = (ev.target.classList && ev.target.classList.contains('avatar-column-no-nav')) || (ev.target.closest && ev.target.closest('.avatar-column-no-nav')); if (avatarColumn) { // Only allow navigation if clicking directly on the avatar link itself var isAvatarLink = ev.target.tagName === 'A' && ev.target.href && ev.target.href.indexOf('/author') !== -1; if (!isAvatarLink) { ev.stopPropagation(); ev.stopImmediatePropagation(); ev.preventDefault(); return false; } } } catch(e) {} }, true); // Capture phase - runs BEFORE other handlers } </script> <div class="w-full border-y sm:border bg-white dark:bg-[#0C1220] bluesky-list-card digest-card card-clickable cursor-pointer group" data-href="/bsky/practicallybetter.bsky.social/post/3ldyi2hkjks2j" role="link" tabindex="0" data-card-type="bsky-post" onclick="if(!event.target.closest('.no-card-link')){ window.location = this.dataset.href }" onkeydown="if((event.key==='Enter' || event.key===' ') && !event.target.closest('.no-card-link')){ window.location = this.dataset.href }"> <div class="px-4 py-3"> <div class="flex items-start gap-4"> <div class="relative w-10 self-stretch flex justify-center no-card-link avatar-column-no-nav" style="min-height:40px; align-self:stretch" onclick="event.stopPropagation(); event.stopImmediatePropagation(); return false;" onkeydown="if(event.key==='Enter' || event.key===' '){ event.stopPropagation(); event.stopImmediatePropagation(); return false; }"> <a href="/author?bsky_handle=practicallybetter.bsky.social" class="no-card-link inline-block flex-shrink-0" aria-label="Practical Betterments" style="align-self: flex-start;"> <img src="https://cdn.bsky.app/img/avatar/plain/did:plc:jwxd2axqquyd5qlcikd6hesz/bafkreifuam6bjsq4c4loo6qtqznl5yhmpw3ij72xixli6pytuabiffhg44@jpeg" alt="practicallybetter.bsky.social" class="w-10 h-10 rounded-full relative z-10" loading="lazy"> </a> </div> <div class="flex-1 min-w-0 -mt-0.5"> <div> <div class="text-[1.1rem] sm:text-[1.15rem] font-semibold text-black flex items-center gap-1"> <a href="/author?bsky_handle=practicallybetter.bsky.social" class="truncate hover:underline text-black no-card-link">Practical Betterments</a> </div> <div class="text-gray-500 text-sm leading-4 -mt-0.5 truncate"> <a href="/author?bsky_handle=practicallybetter.bsky.social" class="hover:underline text-gray-500 no-card-link">@practicallybetter.bsky.social</a> </div> </div> <div class="mt-3 text-[1.2rem] leading-7 break-words text-gray-800 w-[calc(100%+3.5rem)] -ml-[3.5rem]"></div> <a href="https://practicalbetterments.com/leave-a-copy-of-your-keys-with-a-trustworthy-pal/" target="_blank" rel="noopener" class="block mt-2 border rounded overflow-hidden w-[calc(100%+3.5rem)] -ml-[3.5rem] no-card-link"> <img src="https://cdn.bsky.app/img/feed_thumbnail/plain/did:plc:jwxd2axqquyd5qlcikd6hesz/bafkreiguguomshdzduddjpzh7lg6ux576adikuwrj5xrhad3pfwgd2gyeu@jpeg" class="w-full h-40 object-cover" loading="lazy"> <div class="p-2"> <div class="text-sm font-semibold truncate">Leave a copy of your keys with a trustworthy pal</div> <div class="text-xs text-gray-500 truncate">Calling on an emergency locksmith in the middle of the night can be really expensive — especially if they turn out to be just some guy with a crowbar.</div> </div> <div class="border-t px-2 py-2 text-sm text-gray-600 flex items-center gap-2"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M2 12h20"/><path d="M12 2a15.3 15.3 0 0 1 0 20"/><path d="M12 2a15.3 15.3 0 0 0 0 20"/></svg> <span class="truncate">practicalbetterments.com</span> </div> </a> <div class="mt-3 text-xs text-gray-500 flex items-center gap-2 whitespace-nowrap overflow-hidden w-[calc(100%+3.5rem)] -ml-[3.5rem]"> <span>December 23, 2024 at 5:41 PM</span> </div> <div class="border-t my-2 w-[calc(100%+3.5rem)] -ml-[3.5rem]"></div> <div class="mt-3 flex items-center justify-between text-gray-600 text-sm w-[calc(100%+3.5rem)] -ml-[3.5rem] no-card-link" data-controller="bluesky-interactions"> <div class="flex items-center justify-between w-[300px] pr-4 no-card-link"> <div class="hidden" data-post-text-uri="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3ldyi2hkjks2j"> </div> <button type="button" class="flex items-center gap-1 hover:text-black no-card-link" data-action="click->bluesky-auth#requireConnection click->bluesky-interactions#reply" data-bluesky-interactions-reply-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3ldyi2hkjks2j" data-bluesky-interactions-reply-cid-param="bafyreich6xlgmlm6mukagrcc373ae3jwsyezl6plviw5n7ngmtlzwyx74m" data-bluesky-interactions-reply-root-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3ldyi2hkjks2j" data-bluesky-interactions-reply-root-cid-param="bafyreich6xlgmlm6mukagrcc373ae3jwsyezl6plviw5n7ngmtlzwyx74m" data-bluesky-interactions-reply-author-name-param="Practical Betterments" data-bluesky-interactions-reply-author-avatar-param="https://cdn.bsky.app/img/avatar/plain/did:plc:jwxd2axqquyd5qlcikd6hesz/bafkreifuam6bjsq4c4loo6qtqznl5yhmpw3ij72xixli6pytuabiffhg44@jpeg" data-bluesky-interactions-post-path-param="/bsky/practicallybetter.bsky.social/post/3ldyi2hkjks2j" title="Reply" style="pointer-events: auto; cursor: pointer; z-index: 10; position: relative;"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15a4 4 0 0 1-4 4H7l-4 4V7a4 4 0 0 1 4-4h10a4 4 0 0 1 4 4z"/></svg> </button> <div class="relative no-card-link" data-controller="bluesky-repost-menu" data-bluesky-repost-menu-uri-value="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3ldyi2hkjks2j" data-bluesky-repost-menu-cid-value="bafyreich6xlgmlm6mukagrcc373ae3jwsyezl6plviw5n7ngmtlzwyx74m" data-bluesky-repost-menu-repost-uri-value="" data-bluesky-repost-menu-is-reposted-value="false" data-bluesky-repost-menu-author-handle-value="practicallybetter.bsky.social" data-bluesky-repost-menu-post-text-value="" style="pointer-events:auto; cursor:pointer;"> <button type="button" class="flex items-center gap-1 hover:text-black " data-action="click->bluesky-repost-menu#toggleMenu" data-bluesky-interactions-target="repostButton" title="Repost"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg> </button> <div class="hidden absolute left-0 bottom-full mb-3 w-48 rounded-2xl border border-white/10 bg-[#1C2333] text-white shadow-xl overflow-hidden z-50" data-bluesky-repost-menu-target="menu"> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-repost-menu#repost"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg> <span>Repost</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-repost-menu#quote"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg> <span>Quote post</span> </button> </div> </div> <button type="button" class="flex items-center gap-1 hover:text-black no-card-link " data-action="click->bluesky-auth#requireConnection click->bluesky-interactions#toggleLike" data-bluesky-interactions-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3ldyi2hkjks2j" data-bluesky-interactions-cid-param="bafyreich6xlgmlm6mukagrcc373ae3jwsyezl6plviw5n7ngmtlzwyx74m" data-bluesky-interactions-like-uri-param="" data-bluesky-interactions-target="likeButton" title="Like"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 1 0-7.78 7.78L12 21.23l8.84-8.84a5.5 5.5 0 0 0 0-7.78z"/></svg> <span data-bluesky-interactions-target="likeCount">2</span> </button> </div> <div class="flex items-center gap-4 text-gray-500"> <button type="button" class="flex items-center hover:text-black no-card-link" data-controller="share" data-share-url-value="https://oauth.lightnews.app/bsky/practicallybetter.bsky.social/post/3ldyi2hkjks2j" data-share-title-value="Practical Betterments on Lightnews" data-share-text-value="" data-action="click->share#shareSystem" title="Share" style="pointer-events:auto; cursor:pointer;"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 12v7a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-7"/><polyline points="16 6 12 2 8 6"/><line x1="12" y1="2" x2="12" y2="15"/></svg> </button> <div class="relative no-card-link" data-controller="bluesky-options" data-bluesky-options-text-value="" data-bluesky-options-author-handle-value="practicallybetter.bsky.social" data-bluesky-options-author-did-value="did:plc:jwxd2axqquyd5qlcikd6hesz" data-bluesky-options-muted-value="false" data-bluesky-options-blocking-uri-value="" data-bluesky-options-own-value="false" data-bluesky-options-delete-url-value="" data-bluesky-options-post-element-selector-value='[data-card-type="bsky-post"]'> <button type="button" class="inline-flex items-center" data-action="click->bluesky-options#toggleMenu" aria-label="Post options"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="1"/><circle cx="19" cy="12" r="1"/><circle cx="5" cy="12" r="1"/></svg> </button> <div class="hidden absolute right-0 bottom-full mb-3 w-60 rounded-2xl border border-white/10 bg-[#1C2333] text-white shadow-xl overflow-hidden" data-bluesky-options-target="menu"> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-options#translate"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 4h16v16H4z"/><path d="M9 8h6"/><path d="M9 12h6"/><path d="M9 16h6"/></svg> </span> <span>Translate</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-options#copyText"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="8" y="8" width="12" height="12" rx="2"/><path d="M16 8V6a2 2 0 0 0-2-2h-8a2 2 0 0 0-2 2v8"/></svg> </span> <span>Copy post text</span> </button> <div class="border-t border-white/10"></div> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-options#muteAccount"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 9v6h3l5 5V4L7 9H4z"/><line x1="16" y1="9" x2="19" y2="12"/><line x1="19" y1="12" x2="16" y2="15"/></svg> </span> <span data-bluesky-options-target="muteLabel">Mute account</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-options#blockAccount"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 3h18v18H3z"/><path d="M3 3l18 18"/></svg> </span> <span data-bluesky-options-target="blockLabel">Block account</span> </button> </div> </div> </div> </div> </div> </div> </div> </div> <script> // Prevent navigation when clicking in avatar column area - must run in capture phase before global handler // Only initialize once to avoid duplicate listeners if (!window._avatarColumnNoNavInitialized) { window._avatarColumnNoNavInitialized = true; document.addEventListener('click', function(ev) { try { // Check if target itself has the class OR is inside an element with that class var avatarColumn = (ev.target.classList && ev.target.classList.contains('avatar-column-no-nav')) || (ev.target.closest && ev.target.closest('.avatar-column-no-nav')); if (avatarColumn) { // Only allow navigation if clicking directly on the avatar link itself var isAvatarLink = ev.target.tagName === 'A' && ev.target.href && ev.target.href.indexOf('/author') !== -1; if (!isAvatarLink) { ev.stopPropagation(); ev.stopImmediatePropagation(); ev.preventDefault(); return false; } } } catch(e) {} }, true); // Capture phase - runs BEFORE other handlers } </script> <div class="w-full border-y sm:border bg-white dark:bg-[#0C1220] bluesky-list-card digest-card card-clickable cursor-pointer group" data-href="/bsky/practicallybetter.bsky.social/post/3ldgxzvlklc2n" role="link" tabindex="0" data-card-type="bsky-post" onclick="if(!event.target.closest('.no-card-link')){ window.location = this.dataset.href }" onkeydown="if((event.key==='Enter' || event.key===' ') && !event.target.closest('.no-card-link')){ window.location = this.dataset.href }"> <div class="px-4 py-3"> <div class="flex items-start gap-4"> <div class="relative w-10 self-stretch flex justify-center no-card-link avatar-column-no-nav" style="min-height:40px; align-self:stretch" onclick="event.stopPropagation(); event.stopImmediatePropagation(); return false;" onkeydown="if(event.key==='Enter' || event.key===' '){ event.stopPropagation(); event.stopImmediatePropagation(); return false; }"> <a href="/author?bsky_handle=practicallybetter.bsky.social" class="no-card-link inline-block flex-shrink-0" aria-label="Practical Betterments" style="align-self: flex-start;"> <img src="https://cdn.bsky.app/img/avatar/plain/did:plc:jwxd2axqquyd5qlcikd6hesz/bafkreifuam6bjsq4c4loo6qtqznl5yhmpw3ij72xixli6pytuabiffhg44@jpeg" alt="practicallybetter.bsky.social" class="w-10 h-10 rounded-full relative z-10" loading="lazy"> </a> </div> <div class="flex-1 min-w-0 -mt-0.5"> <div> <div class="text-[1.1rem] sm:text-[1.15rem] font-semibold text-black flex items-center gap-1"> <a href="/author?bsky_handle=practicallybetter.bsky.social" class="truncate hover:underline text-black no-card-link">Practical Betterments</a> </div> <div class="text-gray-500 text-sm leading-4 -mt-0.5 truncate"> <a href="/author?bsky_handle=practicallybetter.bsky.social" class="hover:underline text-gray-500 no-card-link">@practicallybetter.bsky.social</a> </div> </div> <div class="mt-3 text-[1.2rem] leading-7 break-words text-gray-800 w-[calc(100%+3.5rem)] -ml-[3.5rem]"></div> <a href="https://practicalbetterments.com/write-a-persuasive-no-junk-mail-sign/" target="_blank" rel="noopener" class="block mt-2 border rounded overflow-hidden w-[calc(100%+3.5rem)] -ml-[3.5rem] no-card-link"> <img src="https://cdn.bsky.app/img/feed_thumbnail/plain/did:plc:jwxd2axqquyd5qlcikd6hesz/bafkreiarzd6yo34xnfzpd4blmbt524hjiexmscer5cfyin7hpqjlrpfoc4@jpeg" class="w-full h-40 object-cover" loading="lazy"> <div class="p-2"> <div class="text-sm font-semibold truncate">Write a persuasive "no junk mail" sign</div> <div class="text-xs text-gray-500 truncate">Receiving junk mail is bad. It wastes time sifting, recycling, and it may even influence you into buying a timeshare or converting to a religion.</div> </div> <div class="border-t px-2 py-2 text-sm text-gray-600 flex items-center gap-2"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M2 12h20"/><path d="M12 2a15.3 15.3 0 0 1 0 20"/><path d="M12 2a15.3 15.3 0 0 0 0 20"/></svg> <span class="truncate">practicalbetterments.com</span> </div> </a> <div class="mt-3 text-xs text-gray-500 flex items-center gap-2 whitespace-nowrap overflow-hidden w-[calc(100%+3.5rem)] -ml-[3.5rem]"> <span>December 16, 2024 at 6:39 PM</span> </div> <div class="border-t my-2 w-[calc(100%+3.5rem)] -ml-[3.5rem]"></div> <div class="mt-3 flex items-center justify-between text-gray-600 text-sm w-[calc(100%+3.5rem)] -ml-[3.5rem] no-card-link" data-controller="bluesky-interactions"> <div class="flex items-center justify-between w-[300px] pr-4 no-card-link"> <div class="hidden" data-post-text-uri="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3ldgxzvlklc2n"> </div> <button type="button" class="flex items-center gap-1 hover:text-black no-card-link" data-action="click->bluesky-auth#requireConnection click->bluesky-interactions#reply" data-bluesky-interactions-reply-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3ldgxzvlklc2n" data-bluesky-interactions-reply-cid-param="bafyreiad4htdbx4v5z4v6gb3pdfd2mmgpl2yij4vjiuhkgobpxmehgsudq" data-bluesky-interactions-reply-root-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3ldgxzvlklc2n" data-bluesky-interactions-reply-root-cid-param="bafyreiad4htdbx4v5z4v6gb3pdfd2mmgpl2yij4vjiuhkgobpxmehgsudq" data-bluesky-interactions-reply-author-name-param="Practical Betterments" data-bluesky-interactions-reply-author-avatar-param="https://cdn.bsky.app/img/avatar/plain/did:plc:jwxd2axqquyd5qlcikd6hesz/bafkreifuam6bjsq4c4loo6qtqznl5yhmpw3ij72xixli6pytuabiffhg44@jpeg" data-bluesky-interactions-post-path-param="/bsky/practicallybetter.bsky.social/post/3ldgxzvlklc2n" title="Reply" style="pointer-events: auto; cursor: pointer; z-index: 10; position: relative;"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15a4 4 0 0 1-4 4H7l-4 4V7a4 4 0 0 1 4-4h10a4 4 0 0 1 4 4z"/></svg> </button> <div class="relative no-card-link" data-controller="bluesky-repost-menu" data-bluesky-repost-menu-uri-value="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3ldgxzvlklc2n" data-bluesky-repost-menu-cid-value="bafyreiad4htdbx4v5z4v6gb3pdfd2mmgpl2yij4vjiuhkgobpxmehgsudq" data-bluesky-repost-menu-repost-uri-value="" data-bluesky-repost-menu-is-reposted-value="false" data-bluesky-repost-menu-author-handle-value="practicallybetter.bsky.social" data-bluesky-repost-menu-post-text-value="" style="pointer-events:auto; cursor:pointer;"> <button type="button" class="flex items-center gap-1 hover:text-black " data-action="click->bluesky-repost-menu#toggleMenu" data-bluesky-interactions-target="repostButton" title="Repost"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg> </button> <div class="hidden absolute left-0 bottom-full mb-3 w-48 rounded-2xl border border-white/10 bg-[#1C2333] text-white shadow-xl overflow-hidden z-50" data-bluesky-repost-menu-target="menu"> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-repost-menu#repost"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg> <span>Repost</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-repost-menu#quote"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg> <span>Quote post</span> </button> </div> </div> <button type="button" class="flex items-center gap-1 hover:text-black no-card-link " data-action="click->bluesky-auth#requireConnection click->bluesky-interactions#toggleLike" data-bluesky-interactions-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3ldgxzvlklc2n" data-bluesky-interactions-cid-param="bafyreiad4htdbx4v5z4v6gb3pdfd2mmgpl2yij4vjiuhkgobpxmehgsudq" data-bluesky-interactions-like-uri-param="" data-bluesky-interactions-target="likeButton" title="Like"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 1 0-7.78 7.78L12 21.23l8.84-8.84a5.5 5.5 0 0 0 0-7.78z"/></svg> <span data-bluesky-interactions-target="likeCount">1</span> </button> </div> <div class="flex items-center gap-4 text-gray-500"> <button type="button" class="flex items-center hover:text-black no-card-link" data-controller="share" data-share-url-value="https://oauth.lightnews.app/bsky/practicallybetter.bsky.social/post/3ldgxzvlklc2n" data-share-title-value="Practical Betterments on Lightnews" data-share-text-value="" data-action="click->share#shareSystem" title="Share" style="pointer-events:auto; cursor:pointer;"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 12v7a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-7"/><polyline points="16 6 12 2 8 6"/><line x1="12" y1="2" x2="12" y2="15"/></svg> </button> <div class="relative no-card-link" data-controller="bluesky-options" data-bluesky-options-text-value="" data-bluesky-options-author-handle-value="practicallybetter.bsky.social" data-bluesky-options-author-did-value="did:plc:jwxd2axqquyd5qlcikd6hesz" data-bluesky-options-muted-value="false" data-bluesky-options-blocking-uri-value="" data-bluesky-options-own-value="false" data-bluesky-options-delete-url-value="" data-bluesky-options-post-element-selector-value='[data-card-type="bsky-post"]'> <button type="button" class="inline-flex items-center" data-action="click->bluesky-options#toggleMenu" aria-label="Post options"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="1"/><circle cx="19" cy="12" r="1"/><circle cx="5" cy="12" r="1"/></svg> </button> <div class="hidden absolute right-0 bottom-full mb-3 w-60 rounded-2xl border border-white/10 bg-[#1C2333] text-white shadow-xl overflow-hidden" data-bluesky-options-target="menu"> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-options#translate"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 4h16v16H4z"/><path d="M9 8h6"/><path d="M9 12h6"/><path d="M9 16h6"/></svg> </span> <span>Translate</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-options#copyText"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="8" y="8" width="12" height="12" rx="2"/><path d="M16 8V6a2 2 0 0 0-2-2h-8a2 2 0 0 0-2 2v8"/></svg> </span> <span>Copy post text</span> </button> <div class="border-t border-white/10"></div> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-options#muteAccount"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 9v6h3l5 5V4L7 9H4z"/><line x1="16" y1="9" x2="19" y2="12"/><line x1="19" y1="12" x2="16" y2="15"/></svg> </span> <span data-bluesky-options-target="muteLabel">Mute account</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-options#blockAccount"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 3h18v18H3z"/><path d="M3 3l18 18"/></svg> </span> <span data-bluesky-options-target="blockLabel">Block account</span> </button> </div> </div> </div> </div> </div> </div> </div> </div> <script> // Prevent navigation when clicking in avatar column area - must run in capture phase before global handler // Only initialize once to avoid duplicate listeners if (!window._avatarColumnNoNavInitialized) { window._avatarColumnNoNavInitialized = true; document.addEventListener('click', function(ev) { try { // Check if target itself has the class OR is inside an element with that class var avatarColumn = (ev.target.classList && ev.target.classList.contains('avatar-column-no-nav')) || (ev.target.closest && ev.target.closest('.avatar-column-no-nav')); if (avatarColumn) { // Only allow navigation if clicking directly on the avatar link itself var isAvatarLink = ev.target.tagName === 'A' && ev.target.href && ev.target.href.indexOf('/author') !== -1; if (!isAvatarLink) { ev.stopPropagation(); ev.stopImmediatePropagation(); ev.preventDefault(); return false; } } } catch(e) {} }, true); // Capture phase - runs BEFORE other handlers } </script> <div class="w-full border-y sm:border bg-white dark:bg-[#0C1220] bluesky-list-card digest-card card-clickable cursor-pointer group" data-href="/bsky/practicallybetter.bsky.social/post/3lcv7c2vx4k2b" role="link" tabindex="0" data-card-type="bsky-post" onclick="if(!event.target.closest('.no-card-link')){ window.location = this.dataset.href }" onkeydown="if((event.key==='Enter' || event.key===' ') && !event.target.closest('.no-card-link')){ window.location = this.dataset.href }"> <div class="px-4 py-3"> <div class="flex items-start gap-4"> <div class="relative w-10 self-stretch flex justify-center no-card-link avatar-column-no-nav" style="min-height:40px; align-self:stretch" onclick="event.stopPropagation(); event.stopImmediatePropagation(); return false;" onkeydown="if(event.key==='Enter' || event.key===' '){ event.stopPropagation(); event.stopImmediatePropagation(); return false; }"> <a href="/author?bsky_handle=practicallybetter.bsky.social" class="no-card-link inline-block flex-shrink-0" aria-label="Practical Betterments" style="align-self: flex-start;"> <img src="https://cdn.bsky.app/img/avatar/plain/did:plc:jwxd2axqquyd5qlcikd6hesz/bafkreifuam6bjsq4c4loo6qtqznl5yhmpw3ij72xixli6pytuabiffhg44@jpeg" alt="practicallybetter.bsky.social" class="w-10 h-10 rounded-full relative z-10" loading="lazy"> </a> </div> <div class="flex-1 min-w-0 -mt-0.5"> <div> <div class="text-[1.1rem] sm:text-[1.15rem] font-semibold text-black flex items-center gap-1"> <a href="/author?bsky_handle=practicallybetter.bsky.social" class="truncate hover:underline text-black no-card-link">Practical Betterments</a> </div> <div class="text-gray-500 text-sm leading-4 -mt-0.5 truncate"> <a href="/author?bsky_handle=practicallybetter.bsky.social" class="hover:underline text-gray-500 no-card-link">@practicallybetter.bsky.social</a> </div> </div> <div class="mt-3 text-[1.2rem] leading-7 break-words text-gray-800 w-[calc(100%+3.5rem)] -ml-[3.5rem]"></div> <a href="https://practicalbetterments.com/setup-a-password-manager/" target="_blank" rel="noopener" class="block mt-2 border rounded overflow-hidden w-[calc(100%+3.5rem)] -ml-[3.5rem] no-card-link"> <img src="https://cdn.bsky.app/img/feed_thumbnail/plain/did:plc:jwxd2axqquyd5qlcikd6hesz/bafkreibzeb7nkldywrxnqv32zkejjfd7m4j4uqcvhhmh5cnf25biqkkt34@jpeg" class="w-full h-40 object-cover" loading="lazy"> <div class="p-2"> <div class="text-sm font-semibold truncate">Setup a password manager</div> <div class="text-xs text-gray-500 truncate"></div> </div> <div class="border-t px-2 py-2 text-sm text-gray-600 flex items-center gap-2"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M2 12h20"/><path d="M12 2a15.3 15.3 0 0 1 0 20"/><path d="M12 2a15.3 15.3 0 0 0 0 20"/></svg> <span class="truncate">practicalbetterments.com</span> </div> </a> <div class="mt-3 text-xs text-gray-500 flex items-center gap-2 whitespace-nowrap overflow-hidden w-[calc(100%+3.5rem)] -ml-[3.5rem]"> <span>December 9, 2024 at 5:01 PM</span> </div> <div class="border-t my-2 w-[calc(100%+3.5rem)] -ml-[3.5rem]"></div> <div class="mt-3 flex items-center justify-between text-gray-600 text-sm w-[calc(100%+3.5rem)] -ml-[3.5rem] no-card-link" data-controller="bluesky-interactions"> <div class="flex items-center justify-between w-[300px] pr-4 no-card-link"> <div class="hidden" data-post-text-uri="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lcv7c2vx4k2b"> </div> <button type="button" class="flex items-center gap-1 hover:text-black no-card-link" data-action="click->bluesky-auth#requireConnection click->bluesky-interactions#reply" data-bluesky-interactions-reply-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lcv7c2vx4k2b" data-bluesky-interactions-reply-cid-param="bafyreia76gvgnxgewasiyl4muh5f37ykvmattdlmo7q2js66hu67vjgrme" data-bluesky-interactions-reply-root-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lcv7c2vx4k2b" data-bluesky-interactions-reply-root-cid-param="bafyreia76gvgnxgewasiyl4muh5f37ykvmattdlmo7q2js66hu67vjgrme" data-bluesky-interactions-reply-author-name-param="Practical Betterments" data-bluesky-interactions-reply-author-avatar-param="https://cdn.bsky.app/img/avatar/plain/did:plc:jwxd2axqquyd5qlcikd6hesz/bafkreifuam6bjsq4c4loo6qtqznl5yhmpw3ij72xixli6pytuabiffhg44@jpeg" data-bluesky-interactions-post-path-param="/bsky/practicallybetter.bsky.social/post/3lcv7c2vx4k2b" title="Reply" style="pointer-events: auto; cursor: pointer; z-index: 10; position: relative;"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15a4 4 0 0 1-4 4H7l-4 4V7a4 4 0 0 1 4-4h10a4 4 0 0 1 4 4z"/></svg> </button> <div class="relative no-card-link" data-controller="bluesky-repost-menu" data-bluesky-repost-menu-uri-value="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lcv7c2vx4k2b" data-bluesky-repost-menu-cid-value="bafyreia76gvgnxgewasiyl4muh5f37ykvmattdlmo7q2js66hu67vjgrme" data-bluesky-repost-menu-repost-uri-value="" data-bluesky-repost-menu-is-reposted-value="false" data-bluesky-repost-menu-author-handle-value="practicallybetter.bsky.social" data-bluesky-repost-menu-post-text-value="" style="pointer-events:auto; cursor:pointer;"> <button type="button" class="flex items-center gap-1 hover:text-black " data-action="click->bluesky-repost-menu#toggleMenu" data-bluesky-interactions-target="repostButton" title="Repost"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg> <span data-bluesky-interactions-target="repostCount">1</span> </button> <div class="hidden absolute left-0 bottom-full mb-3 w-48 rounded-2xl border border-white/10 bg-[#1C2333] text-white shadow-xl overflow-hidden z-50" data-bluesky-repost-menu-target="menu"> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-repost-menu#repost"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg> <span>Repost</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-repost-menu#quote"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg> <span>Quote post</span> </button> </div> </div> <button type="button" class="flex items-center gap-1 hover:text-black no-card-link " data-action="click->bluesky-auth#requireConnection click->bluesky-interactions#toggleLike" data-bluesky-interactions-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lcv7c2vx4k2b" data-bluesky-interactions-cid-param="bafyreia76gvgnxgewasiyl4muh5f37ykvmattdlmo7q2js66hu67vjgrme" data-bluesky-interactions-like-uri-param="" data-bluesky-interactions-target="likeButton" title="Like"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 1 0-7.78 7.78L12 21.23l8.84-8.84a5.5 5.5 0 0 0 0-7.78z"/></svg> <span data-bluesky-interactions-target="likeCount">3</span> </button> </div> <div class="flex items-center gap-4 text-gray-500"> <button type="button" class="flex items-center hover:text-black no-card-link" data-controller="share" data-share-url-value="https://oauth.lightnews.app/bsky/practicallybetter.bsky.social/post/3lcv7c2vx4k2b" data-share-title-value="Practical Betterments on Lightnews" data-share-text-value="" data-action="click->share#shareSystem" title="Share" style="pointer-events:auto; cursor:pointer;"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 12v7a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-7"/><polyline points="16 6 12 2 8 6"/><line x1="12" y1="2" x2="12" y2="15"/></svg> </button> <div class="relative no-card-link" data-controller="bluesky-options" data-bluesky-options-text-value="" data-bluesky-options-author-handle-value="practicallybetter.bsky.social" data-bluesky-options-author-did-value="did:plc:jwxd2axqquyd5qlcikd6hesz" data-bluesky-options-muted-value="false" data-bluesky-options-blocking-uri-value="" data-bluesky-options-own-value="false" data-bluesky-options-delete-url-value="" data-bluesky-options-post-element-selector-value='[data-card-type="bsky-post"]'> <button type="button" class="inline-flex items-center" data-action="click->bluesky-options#toggleMenu" aria-label="Post options"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="1"/><circle cx="19" cy="12" r="1"/><circle cx="5" cy="12" r="1"/></svg> </button> <div class="hidden absolute right-0 bottom-full mb-3 w-60 rounded-2xl border border-white/10 bg-[#1C2333] text-white shadow-xl overflow-hidden" data-bluesky-options-target="menu"> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-options#translate"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 4h16v16H4z"/><path d="M9 8h6"/><path d="M9 12h6"/><path d="M9 16h6"/></svg> </span> <span>Translate</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-options#copyText"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="8" y="8" width="12" height="12" rx="2"/><path d="M16 8V6a2 2 0 0 0-2-2h-8a2 2 0 0 0-2 2v8"/></svg> </span> <span>Copy post text</span> </button> <div class="border-t border-white/10"></div> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-options#muteAccount"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 9v6h3l5 5V4L7 9H4z"/><line x1="16" y1="9" x2="19" y2="12"/><line x1="19" y1="12" x2="16" y2="15"/></svg> </span> <span data-bluesky-options-target="muteLabel">Mute account</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-options#blockAccount"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 3h18v18H3z"/><path d="M3 3l18 18"/></svg> </span> <span data-bluesky-options-target="blockLabel">Block account</span> </button> </div> </div> </div> </div> </div> </div> </div> </div> <script> // Prevent navigation when clicking in avatar column area - must run in capture phase before global handler // Only initialize once to avoid duplicate listeners if (!window._avatarColumnNoNavInitialized) { window._avatarColumnNoNavInitialized = true; document.addEventListener('click', function(ev) { try { // Check if target itself has the class OR is inside an element with that class var avatarColumn = (ev.target.classList && ev.target.classList.contains('avatar-column-no-nav')) || (ev.target.closest && ev.target.closest('.avatar-column-no-nav')); if (avatarColumn) { // Only allow navigation if clicking directly on the avatar link itself var isAvatarLink = ev.target.tagName === 'A' && ev.target.href && ev.target.href.indexOf('/author') !== -1; if (!isAvatarLink) { ev.stopPropagation(); ev.stopImmediatePropagation(); ev.preventDefault(); return false; } } } catch(e) {} }, true); // Capture phase - runs BEFORE other handlers } </script> <div class="w-full border-y sm:border bg-white dark:bg-[#0C1220] bluesky-list-card digest-card card-clickable cursor-pointer group" data-href="/bsky/practicallybetter.bsky.social/post/3lco57vc3ds2o" role="link" tabindex="0" data-card-type="bsky-post" onclick="if(!event.target.closest('.no-card-link')){ window.location = this.dataset.href }" onkeydown="if((event.key==='Enter' || event.key===' ') && !event.target.closest('.no-card-link')){ window.location = this.dataset.href }"> <div class="px-4 py-3"> <div class="flex items-start gap-4"> <div class="relative w-10 self-stretch flex justify-center no-card-link avatar-column-no-nav" style="min-height:40px; align-self:stretch" onclick="event.stopPropagation(); event.stopImmediatePropagation(); return false;" onkeydown="if(event.key==='Enter' || event.key===' '){ event.stopPropagation(); event.stopImmediatePropagation(); return false; }"> <a href="/author?bsky_handle=practicallybetter.bsky.social" class="no-card-link inline-block flex-shrink-0" aria-label="Practical Betterments" style="align-self: flex-start;"> <img src="https://cdn.bsky.app/img/avatar/plain/did:plc:jwxd2axqquyd5qlcikd6hesz/bafkreifuam6bjsq4c4loo6qtqznl5yhmpw3ij72xixli6pytuabiffhg44@jpeg" alt="practicallybetter.bsky.social" class="w-10 h-10 rounded-full relative z-10" loading="lazy"> </a> </div> <div class="flex-1 min-w-0 -mt-0.5"> <div> <div class="text-[1.1rem] sm:text-[1.15rem] font-semibold text-black flex items-center gap-1"> <a href="/author?bsky_handle=practicallybetter.bsky.social" class="truncate hover:underline text-black no-card-link">Practical Betterments</a> </div> <div class="text-gray-500 text-sm leading-4 -mt-0.5 truncate"> <a href="/author?bsky_handle=practicallybetter.bsky.social" class="hover:underline text-gray-500 no-card-link">@practicallybetter.bsky.social</a> </div> </div> <div class="mt-3 text-[1.2rem] leading-7 break-words text-gray-800 w-[calc(100%+3.5rem)] -ml-[3.5rem]">Practical Betterments are not a replacement for therapy, surgery, radical societal change, or even just being a reasonable adult. Cutting the end off your toothbrush will not find you true love.<br><br>But wouldn't it be easier to find true love without lugging round 5g of unnecessary toothbrush weight?</div> <a href="https://practicalbetterments.com/" target="_blank" rel="noopener" class="block mt-2 border rounded overflow-hidden w-[calc(100%+3.5rem)] -ml-[3.5rem] no-card-link"> <img src="https://cdn.bsky.app/img/feed_thumbnail/plain/did:plc:jwxd2axqquyd5qlcikd6hesz/bafkreibmtfcfkgurwm3zqqq3af5yhauqwwhtdfrvzmmov6ryz3vjc5tl2m@jpeg" class="w-full h-40 object-cover" loading="lazy"> <div class="p-2"> <div class="text-sm font-semibold truncate">Practical betterments</div> <div class="text-xs text-gray-500 truncate">A collection of one-off actions to improve your life continuously — however marginally</div> </div> <div class="border-t px-2 py-2 text-sm text-gray-600 flex items-center gap-2"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M2 12h20"/><path d="M12 2a15.3 15.3 0 0 1 0 20"/><path d="M12 2a15.3 15.3 0 0 0 0 20"/></svg> <span class="truncate">practicalbetterments.com</span> </div> </a> <div class="mt-3 text-xs text-gray-500 flex items-center gap-2 whitespace-nowrap overflow-hidden w-[calc(100%+3.5rem)] -ml-[3.5rem]"> <span>December 6, 2024 at 9:35 PM</span> </div> <div class="border-t my-2 w-[calc(100%+3.5rem)] -ml-[3.5rem]"></div> <div class="mt-3 flex items-center justify-between text-gray-600 text-sm w-[calc(100%+3.5rem)] -ml-[3.5rem] no-card-link" data-controller="bluesky-interactions"> <div class="flex items-center justify-between w-[300px] pr-4 no-card-link"> <div class="hidden" data-post-text-uri="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lco57vc3ds2o"> Practical Betterments are not a replacement for therapy, surgery, radical societal change, or even just being a reasonable adult. Cutting the end off your toothbrush will not find you true love.<br><br>But wouldn't it be easier to find true love without lugging round 5g of unnecessary toothbrush weight? </div> <button type="button" class="flex items-center gap-1 hover:text-black no-card-link" data-action="click->bluesky-auth#requireConnection click->bluesky-interactions#reply" data-bluesky-interactions-reply-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lco57vc3ds2o" data-bluesky-interactions-reply-cid-param="bafyreihyt7pqvuza65dqkyl3qbg2eo3crh3ceasgstavmm7dd7fumjgqri" data-bluesky-interactions-reply-root-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lco57vc3ds2o" data-bluesky-interactions-reply-root-cid-param="bafyreihyt7pqvuza65dqkyl3qbg2eo3crh3ceasgstavmm7dd7fumjgqri" data-bluesky-interactions-reply-author-name-param="Practical Betterments" data-bluesky-interactions-reply-author-avatar-param="https://cdn.bsky.app/img/avatar/plain/did:plc:jwxd2axqquyd5qlcikd6hesz/bafkreifuam6bjsq4c4loo6qtqznl5yhmpw3ij72xixli6pytuabiffhg44@jpeg" data-bluesky-interactions-post-path-param="/bsky/practicallybetter.bsky.social/post/3lco57vc3ds2o" title="Reply" style="pointer-events: auto; cursor: pointer; z-index: 10; position: relative;"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15a4 4 0 0 1-4 4H7l-4 4V7a4 4 0 0 1 4-4h10a4 4 0 0 1 4 4z"/></svg> </button> <div class="relative no-card-link" data-controller="bluesky-repost-menu" data-bluesky-repost-menu-uri-value="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lco57vc3ds2o" data-bluesky-repost-menu-cid-value="bafyreihyt7pqvuza65dqkyl3qbg2eo3crh3ceasgstavmm7dd7fumjgqri" data-bluesky-repost-menu-repost-uri-value="" data-bluesky-repost-menu-is-reposted-value="false" data-bluesky-repost-menu-author-handle-value="practicallybetter.bsky.social" data-bluesky-repost-menu-post-text-value="Practical Betterments are not a replacement for therapy, surgery, radical societal change, or even just being a reasonable adult. Cutting the end off your toothbrush will not find you true love. But wouldn't it be easier to find true love without lugging round 5g of unnecessary toothbrush weight?" style="pointer-events:auto; cursor:pointer;"> <button type="button" class="flex items-center gap-1 hover:text-black " data-action="click->bluesky-repost-menu#toggleMenu" data-bluesky-interactions-target="repostButton" title="Repost"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg> <span data-bluesky-interactions-target="repostCount">2</span> </button> <div class="hidden absolute left-0 bottom-full mb-3 w-48 rounded-2xl border border-white/10 bg-[#1C2333] text-white shadow-xl overflow-hidden z-50" data-bluesky-repost-menu-target="menu"> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-repost-menu#repost"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg> <span>Repost</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-repost-menu#quote"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg> <span>Quote post</span> </button> </div> </div> <button type="button" class="flex items-center gap-1 hover:text-black no-card-link " data-action="click->bluesky-auth#requireConnection click->bluesky-interactions#toggleLike" data-bluesky-interactions-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lco57vc3ds2o" data-bluesky-interactions-cid-param="bafyreihyt7pqvuza65dqkyl3qbg2eo3crh3ceasgstavmm7dd7fumjgqri" data-bluesky-interactions-like-uri-param="" data-bluesky-interactions-target="likeButton" title="Like"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 1 0-7.78 7.78L12 21.23l8.84-8.84a5.5 5.5 0 0 0 0-7.78z"/></svg> <span data-bluesky-interactions-target="likeCount">3</span> </button> </div> <div class="flex items-center gap-4 text-gray-500"> <button type="button" class="flex items-center hover:text-black no-card-link" data-controller="share" data-share-url-value="https://oauth.lightnews.app/bsky/practicallybetter.bsky.social/post/3lco57vc3ds2o" data-share-title-value="Practical Betterments on Lightnews" data-share-text-value="Practical Betterments are not a replacement for therapy, surgery, radical societal change, or even just being a reasonable adult. Cutting th…" data-action="click->share#shareSystem" title="Share" style="pointer-events:auto; cursor:pointer;"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 12v7a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-7"/><polyline points="16 6 12 2 8 6"/><line x1="12" y1="2" x2="12" y2="15"/></svg> </button> <div class="relative no-card-link" data-controller="bluesky-options" data-bluesky-options-text-value="Practical Betterments are not a replacement for therapy, surgery, radical societal change, or even just being a reasonable adult. Cutting the end off your toothbrush will not find you true love. But wouldn't it be easier to find true love without lugging round 5g of unnecessary toothbrush weight?" data-bluesky-options-author-handle-value="practicallybetter.bsky.social" data-bluesky-options-author-did-value="did:plc:jwxd2axqquyd5qlcikd6hesz" data-bluesky-options-muted-value="false" data-bluesky-options-blocking-uri-value="" data-bluesky-options-own-value="false" data-bluesky-options-delete-url-value="" data-bluesky-options-post-element-selector-value='[data-card-type="bsky-post"]'> <button type="button" class="inline-flex items-center" data-action="click->bluesky-options#toggleMenu" aria-label="Post options"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="1"/><circle cx="19" cy="12" r="1"/><circle cx="5" cy="12" r="1"/></svg> </button> <div class="hidden absolute right-0 bottom-full mb-3 w-60 rounded-2xl border border-white/10 bg-[#1C2333] text-white shadow-xl overflow-hidden" data-bluesky-options-target="menu"> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-options#translate"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 4h16v16H4z"/><path d="M9 8h6"/><path d="M9 12h6"/><path d="M9 16h6"/></svg> </span> <span>Translate</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-options#copyText"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="8" y="8" width="12" height="12" rx="2"/><path d="M16 8V6a2 2 0 0 0-2-2h-8a2 2 0 0 0-2 2v8"/></svg> </span> <span>Copy post text</span> </button> <div class="border-t border-white/10"></div> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-options#muteAccount"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 9v6h3l5 5V4L7 9H4z"/><line x1="16" y1="9" x2="19" y2="12"/><line x1="19" y1="12" x2="16" y2="15"/></svg> </span> <span data-bluesky-options-target="muteLabel">Mute account</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-options#blockAccount"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 3h18v18H3z"/><path d="M3 3l18 18"/></svg> </span> <span data-bluesky-options-target="blockLabel">Block account</span> </button> </div> </div> </div> </div> </div> </div> </div> </div> <script> // Prevent navigation when clicking in avatar column area - must run in capture phase before global handler // Only initialize once to avoid duplicate listeners if (!window._avatarColumnNoNavInitialized) { window._avatarColumnNoNavInitialized = true; document.addEventListener('click', function(ev) { try { // Check if target itself has the class OR is inside an element with that class var avatarColumn = (ev.target.classList && ev.target.classList.contains('avatar-column-no-nav')) || (ev.target.closest && ev.target.closest('.avatar-column-no-nav')); if (avatarColumn) { // Only allow navigation if clicking directly on the avatar link itself var isAvatarLink = ev.target.tagName === 'A' && ev.target.href && ev.target.href.indexOf('/author') !== -1; if (!isAvatarLink) { ev.stopPropagation(); ev.stopImmediatePropagation(); ev.preventDefault(); return false; } } } catch(e) {} }, true); // Capture phase - runs BEFORE other handlers } </script> <div class="w-full border-y sm:border bg-white dark:bg-[#0C1220] bluesky-list-card digest-card card-clickable cursor-pointer group" data-href="/bsky/practicallybetter.bsky.social/post/3lco3sqfxok24" role="link" tabindex="0" data-card-type="bsky-post" onclick="if(!event.target.closest('.no-card-link')){ window.location = this.dataset.href }" onkeydown="if((event.key==='Enter' || event.key===' ') && !event.target.closest('.no-card-link')){ window.location = this.dataset.href }"> <div class="px-4 py-3"> <div class="flex items-start gap-4"> <div class="relative w-10 self-stretch flex justify-center no-card-link avatar-column-no-nav" style="min-height:40px; align-self:stretch" onclick="event.stopPropagation(); event.stopImmediatePropagation(); return false;" onkeydown="if(event.key==='Enter' || event.key===' '){ event.stopPropagation(); event.stopImmediatePropagation(); return false; }"> <a href="/author?bsky_handle=practicallybetter.bsky.social" class="no-card-link inline-block flex-shrink-0" aria-label="Practical Betterments" style="align-self: flex-start;"> <img src="https://cdn.bsky.app/img/avatar/plain/did:plc:jwxd2axqquyd5qlcikd6hesz/bafkreifuam6bjsq4c4loo6qtqznl5yhmpw3ij72xixli6pytuabiffhg44@jpeg" alt="practicallybetter.bsky.social" class="w-10 h-10 rounded-full relative z-10" loading="lazy"> </a> </div> <div class="flex-1 min-w-0 -mt-0.5"> <div> <div class="text-[1.1rem] sm:text-[1.15rem] font-semibold text-black flex items-center gap-1"> <a href="/author?bsky_handle=practicallybetter.bsky.social" class="truncate hover:underline text-black no-card-link">Practical Betterments</a> </div> <div class="text-gray-500 text-sm leading-4 -mt-0.5 truncate"> <a href="/author?bsky_handle=practicallybetter.bsky.social" class="hover:underline text-gray-500 no-card-link">@practicallybetter.bsky.social</a> </div> </div> <div class="mt-3 text-[1.2rem] leading-7 break-words text-gray-800 w-[calc(100%+3.5rem)] -ml-[3.5rem]"></div> <a href="https://practicalbetterments.com/order-and-orient-the-keys-on-your-keychain/" target="_blank" rel="noopener" class="block mt-2 border rounded overflow-hidden w-[calc(100%+3.5rem)] -ml-[3.5rem] no-card-link"> <img src="https://cdn.bsky.app/img/feed_thumbnail/plain/did:plc:jwxd2axqquyd5qlcikd6hesz/bafkreiaebdyv5j7ok7fczdtlc4q4af7rdg22v4ftg6q3zmy326drru4f3i@jpeg" class="w-full h-40 object-cover" loading="lazy"> <div class="p-2"> <div class="text-sm font-semibold truncate">Order and orient the keys on your keychain</div> <div class="text-xs text-gray-500 truncate"></div> </div> <div class="border-t px-2 py-2 text-sm text-gray-600 flex items-center gap-2"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M2 12h20"/><path d="M12 2a15.3 15.3 0 0 1 0 20"/><path d="M12 2a15.3 15.3 0 0 0 0 20"/></svg> <span class="truncate">practicalbetterments.com</span> </div> </a> <div class="mt-3 text-xs text-gray-500 flex items-center gap-2 whitespace-nowrap overflow-hidden w-[calc(100%+3.5rem)] -ml-[3.5rem]"> <span>December 6, 2024 at 9:10 PM</span> </div> <div class="border-t my-2 w-[calc(100%+3.5rem)] -ml-[3.5rem]"></div> <div class="mt-3 flex items-center justify-between text-gray-600 text-sm w-[calc(100%+3.5rem)] -ml-[3.5rem] no-card-link" data-controller="bluesky-interactions"> <div class="flex items-center justify-between w-[300px] pr-4 no-card-link"> <div class="hidden" data-post-text-uri="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lco3sqfxok24"> </div> <button type="button" class="flex items-center gap-1 hover:text-black no-card-link" data-action="click->bluesky-auth#requireConnection click->bluesky-interactions#reply" data-bluesky-interactions-reply-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lco3sqfxok24" data-bluesky-interactions-reply-cid-param="bafyreidajmigjufjfurz3flxc5chikyjsvvnls454jlvor2z55mmbucabu" data-bluesky-interactions-reply-root-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lco3sqfxok24" data-bluesky-interactions-reply-root-cid-param="bafyreidajmigjufjfurz3flxc5chikyjsvvnls454jlvor2z55mmbucabu" data-bluesky-interactions-reply-author-name-param="Practical Betterments" data-bluesky-interactions-reply-author-avatar-param="https://cdn.bsky.app/img/avatar/plain/did:plc:jwxd2axqquyd5qlcikd6hesz/bafkreifuam6bjsq4c4loo6qtqznl5yhmpw3ij72xixli6pytuabiffhg44@jpeg" data-bluesky-interactions-post-path-param="/bsky/practicallybetter.bsky.social/post/3lco3sqfxok24" title="Reply" style="pointer-events: auto; cursor: pointer; z-index: 10; position: relative;"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15a4 4 0 0 1-4 4H7l-4 4V7a4 4 0 0 1 4-4h10a4 4 0 0 1 4 4z"/></svg> </button> <div class="relative no-card-link" data-controller="bluesky-repost-menu" data-bluesky-repost-menu-uri-value="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lco3sqfxok24" data-bluesky-repost-menu-cid-value="bafyreidajmigjufjfurz3flxc5chikyjsvvnls454jlvor2z55mmbucabu" data-bluesky-repost-menu-repost-uri-value="" data-bluesky-repost-menu-is-reposted-value="false" data-bluesky-repost-menu-author-handle-value="practicallybetter.bsky.social" data-bluesky-repost-menu-post-text-value="" style="pointer-events:auto; cursor:pointer;"> <button type="button" class="flex items-center gap-1 hover:text-black " data-action="click->bluesky-repost-menu#toggleMenu" data-bluesky-interactions-target="repostButton" title="Repost"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg> </button> <div class="hidden absolute left-0 bottom-full mb-3 w-48 rounded-2xl border border-white/10 bg-[#1C2333] text-white shadow-xl overflow-hidden z-50" data-bluesky-repost-menu-target="menu"> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-repost-menu#repost"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg> <span>Repost</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-repost-menu#quote"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg> <span>Quote post</span> </button> </div> </div> <button type="button" class="flex items-center gap-1 hover:text-black no-card-link " data-action="click->bluesky-auth#requireConnection click->bluesky-interactions#toggleLike" data-bluesky-interactions-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lco3sqfxok24" data-bluesky-interactions-cid-param="bafyreidajmigjufjfurz3flxc5chikyjsvvnls454jlvor2z55mmbucabu" data-bluesky-interactions-like-uri-param="" data-bluesky-interactions-target="likeButton" title="Like"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 1 0-7.78 7.78L12 21.23l8.84-8.84a5.5 5.5 0 0 0 0-7.78z"/></svg> <span data-bluesky-interactions-target="likeCount">1</span> </button> </div> <div class="flex items-center gap-4 text-gray-500"> <button type="button" class="flex items-center hover:text-black no-card-link" data-controller="share" data-share-url-value="https://oauth.lightnews.app/bsky/practicallybetter.bsky.social/post/3lco3sqfxok24" data-share-title-value="Practical Betterments on Lightnews" data-share-text-value="" data-action="click->share#shareSystem" title="Share" style="pointer-events:auto; cursor:pointer;"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 12v7a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-7"/><polyline points="16 6 12 2 8 6"/><line x1="12" y1="2" x2="12" y2="15"/></svg> </button> <div class="relative no-card-link" data-controller="bluesky-options" data-bluesky-options-text-value="" data-bluesky-options-author-handle-value="practicallybetter.bsky.social" data-bluesky-options-author-did-value="did:plc:jwxd2axqquyd5qlcikd6hesz" data-bluesky-options-muted-value="false" data-bluesky-options-blocking-uri-value="" data-bluesky-options-own-value="false" data-bluesky-options-delete-url-value="" data-bluesky-options-post-element-selector-value='[data-card-type="bsky-post"]'> <button type="button" class="inline-flex items-center" data-action="click->bluesky-options#toggleMenu" aria-label="Post options"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="1"/><circle cx="19" cy="12" r="1"/><circle cx="5" cy="12" r="1"/></svg> </button> <div class="hidden absolute right-0 bottom-full mb-3 w-60 rounded-2xl border border-white/10 bg-[#1C2333] text-white shadow-xl overflow-hidden" data-bluesky-options-target="menu"> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-options#translate"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 4h16v16H4z"/><path d="M9 8h6"/><path d="M9 12h6"/><path d="M9 16h6"/></svg> </span> <span>Translate</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-options#copyText"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="8" y="8" width="12" height="12" rx="2"/><path d="M16 8V6a2 2 0 0 0-2-2h-8a2 2 0 0 0-2 2v8"/></svg> </span> <span>Copy post text</span> </button> <div class="border-t border-white/10"></div> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-options#muteAccount"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 9v6h3l5 5V4L7 9H4z"/><line x1="16" y1="9" x2="19" y2="12"/><line x1="19" y1="12" x2="16" y2="15"/></svg> </span> <span data-bluesky-options-target="muteLabel">Mute account</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-options#blockAccount"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 3h18v18H3z"/><path d="M3 3l18 18"/></svg> </span> <span data-bluesky-options-target="blockLabel">Block account</span> </button> </div> </div> </div> </div> </div> </div> </div> </div> <script> // Prevent navigation when clicking in avatar column area - must run in capture phase before global handler // Only initialize once to avoid duplicate listeners if (!window._avatarColumnNoNavInitialized) { window._avatarColumnNoNavInitialized = true; document.addEventListener('click', function(ev) { try { // Check if target itself has the class OR is inside an element with that class var avatarColumn = (ev.target.classList && ev.target.classList.contains('avatar-column-no-nav')) || (ev.target.closest && ev.target.closest('.avatar-column-no-nav')); if (avatarColumn) { // Only allow navigation if clicking directly on the avatar link itself var isAvatarLink = ev.target.tagName === 'A' && ev.target.href && ev.target.href.indexOf('/author') !== -1; if (!isAvatarLink) { ev.stopPropagation(); ev.stopImmediatePropagation(); ev.preventDefault(); return false; } } } catch(e) {} }, true); // Capture phase - runs BEFORE other handlers } </script> <div class="w-full border-y sm:border bg-white dark:bg-[#0C1220] bluesky-list-card digest-card card-clickable cursor-pointer group" data-href="/bsky/practicallybetter.bsky.social/post/3lco2qlggv22h" role="link" tabindex="0" data-card-type="bsky-post" onclick="if(!event.target.closest('.no-card-link')){ window.location = this.dataset.href }" onkeydown="if((event.key==='Enter' || event.key===' ') && !event.target.closest('.no-card-link')){ window.location = this.dataset.href }"> <div class="px-4 py-3"> <div class="flex items-start gap-4"> <div class="relative w-10 self-stretch flex justify-center no-card-link avatar-column-no-nav" style="min-height:40px; align-self:stretch" onclick="event.stopPropagation(); event.stopImmediatePropagation(); return false;" onkeydown="if(event.key==='Enter' || event.key===' '){ event.stopPropagation(); event.stopImmediatePropagation(); return false; }"> <a href="/author?bsky_handle=practicallybetter.bsky.social" class="no-card-link inline-block flex-shrink-0" aria-label="Practical Betterments" style="align-self: flex-start;"> <img src="https://cdn.bsky.app/img/avatar/plain/did:plc:jwxd2axqquyd5qlcikd6hesz/bafkreifuam6bjsq4c4loo6qtqznl5yhmpw3ij72xixli6pytuabiffhg44@jpeg" alt="practicallybetter.bsky.social" class="w-10 h-10 rounded-full relative z-10" loading="lazy"> </a> </div> <div class="flex-1 min-w-0 -mt-0.5"> <div> <div class="text-[1.1rem] sm:text-[1.15rem] font-semibold text-black flex items-center gap-1"> <a href="/author?bsky_handle=practicallybetter.bsky.social" class="truncate hover:underline text-black no-card-link">Practical Betterments</a> </div> <div class="text-gray-500 text-sm leading-4 -mt-0.5 truncate"> <a href="/author?bsky_handle=practicallybetter.bsky.social" class="hover:underline text-gray-500 no-card-link">@practicallybetter.bsky.social</a> </div> </div> <div class="mt-3 text-[1.2rem] leading-7 break-words text-gray-800 w-[calc(100%+3.5rem)] -ml-[3.5rem]">Trying the wrong key, then fumbling and trying the wrong key again wastes valuable time and mental energy.<br><br>It's especially annoying when it's dark and raining.<br><br>The solution is to drill holes in your keys.<br><br><a href="https://practicalbetterments.com/drill-holes-in-your-keys/" class="hover:underline text-blue-600 dark:text-sky-400 no-card-link" target="_blank" rel="noopener" data-link="bsky">practicalbetterments.com/drill-holes-...</a></div> <div class="mt-3 text-xs text-gray-500 flex items-center gap-2 whitespace-nowrap overflow-hidden w-[calc(100%+3.5rem)] -ml-[3.5rem]"> <span>December 6, 2024 at 8:51 PM</span> </div> <div class="border-t my-2 w-[calc(100%+3.5rem)] -ml-[3.5rem]"></div> <div class="mt-3 flex items-center justify-between text-gray-600 text-sm w-[calc(100%+3.5rem)] -ml-[3.5rem] no-card-link" data-controller="bluesky-interactions"> <div class="flex items-center justify-between w-[300px] pr-4 no-card-link"> <div class="hidden" data-post-text-uri="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lco2qlggv22h"> Trying the wrong key, then fumbling and trying the wrong key again wastes valuable time and mental energy.<br><br>It's especially annoying when it's dark and raining.<br><br>The solution is to drill holes in your keys.<br><br><a href="https://practicalbetterments.com/drill-holes-in-your-keys/" class="hover:underline text-blue-600 dark:text-sky-400 no-card-link" target="_blank" rel="noopener" data-link="bsky">practicalbetterments.com/drill-holes-...</a> </div> <button type="button" class="flex items-center gap-1 hover:text-black no-card-link" data-action="click->bluesky-auth#requireConnection click->bluesky-interactions#reply" data-bluesky-interactions-reply-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lco2qlggv22h" data-bluesky-interactions-reply-cid-param="bafyreidfigrziubko3wsiro53jevrh6zrj23ej5tqmurocjxouhh4c7qfa" data-bluesky-interactions-reply-root-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lco2qlggv22h" data-bluesky-interactions-reply-root-cid-param="bafyreidfigrziubko3wsiro53jevrh6zrj23ej5tqmurocjxouhh4c7qfa" data-bluesky-interactions-reply-author-name-param="Practical Betterments" data-bluesky-interactions-reply-author-avatar-param="https://cdn.bsky.app/img/avatar/plain/did:plc:jwxd2axqquyd5qlcikd6hesz/bafkreifuam6bjsq4c4loo6qtqznl5yhmpw3ij72xixli6pytuabiffhg44@jpeg" data-bluesky-interactions-post-path-param="/bsky/practicallybetter.bsky.social/post/3lco2qlggv22h" title="Reply" style="pointer-events: auto; cursor: pointer; z-index: 10; position: relative;"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15a4 4 0 0 1-4 4H7l-4 4V7a4 4 0 0 1 4-4h10a4 4 0 0 1 4 4z"/></svg> </button> <div class="relative no-card-link" data-controller="bluesky-repost-menu" data-bluesky-repost-menu-uri-value="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lco2qlggv22h" data-bluesky-repost-menu-cid-value="bafyreidfigrziubko3wsiro53jevrh6zrj23ej5tqmurocjxouhh4c7qfa" data-bluesky-repost-menu-repost-uri-value="" data-bluesky-repost-menu-is-reposted-value="false" data-bluesky-repost-menu-author-handle-value="practicallybetter.bsky.social" data-bluesky-repost-menu-post-text-value="Trying the wrong key, then fumbling and trying the wrong key again wastes valuable time and mental energy. It's especially annoying when it's dark and raining. The solution is to drill holes in your keys. practicalbetterments.com/drill-holes-..." style="pointer-events:auto; cursor:pointer;"> <button type="button" class="flex items-center gap-1 hover:text-black " data-action="click->bluesky-repost-menu#toggleMenu" data-bluesky-interactions-target="repostButton" title="Repost"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg> </button> <div class="hidden absolute left-0 bottom-full mb-3 w-48 rounded-2xl border border-white/10 bg-[#1C2333] text-white shadow-xl overflow-hidden z-50" data-bluesky-repost-menu-target="menu"> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-repost-menu#repost"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg> <span>Repost</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-repost-menu#quote"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg> <span>Quote post</span> </button> </div> </div> <button type="button" class="flex items-center gap-1 hover:text-black no-card-link " data-action="click->bluesky-auth#requireConnection click->bluesky-interactions#toggleLike" data-bluesky-interactions-uri-param="at://did:plc:jwxd2axqquyd5qlcikd6hesz/app.bsky.feed.post/3lco2qlggv22h" data-bluesky-interactions-cid-param="bafyreidfigrziubko3wsiro53jevrh6zrj23ej5tqmurocjxouhh4c7qfa" data-bluesky-interactions-like-uri-param="" data-bluesky-interactions-target="likeButton" title="Like"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 1 0-7.78 7.78L12 21.23l8.84-8.84a5.5 5.5 0 0 0 0-7.78z"/></svg> <span data-bluesky-interactions-target="likeCount">2</span> </button> </div> <div class="flex items-center gap-4 text-gray-500"> <button type="button" class="flex items-center hover:text-black no-card-link" data-controller="share" data-share-url-value="https://oauth.lightnews.app/bsky/practicallybetter.bsky.social/post/3lco2qlggv22h" data-share-title-value="Practical Betterments on Lightnews" data-share-text-value="Trying the wrong key, then fumbling and trying the wrong key again wastes valuable time and mental energy. It's especially annoying when it'…" data-action="click->share#shareSystem" title="Share" style="pointer-events:auto; cursor:pointer;"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 12v7a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-7"/><polyline points="16 6 12 2 8 6"/><line x1="12" y1="2" x2="12" y2="15"/></svg> </button> <div class="relative no-card-link" data-controller="bluesky-options" data-bluesky-options-text-value="Trying the wrong key, then fumbling and trying the wrong key again wastes valuable time and mental energy. It's especially annoying when it's dark and raining. The solution is to drill holes in your keys. practicalbetterments.com/drill-holes-..." data-bluesky-options-author-handle-value="practicallybetter.bsky.social" data-bluesky-options-author-did-value="did:plc:jwxd2axqquyd5qlcikd6hesz" data-bluesky-options-muted-value="false" data-bluesky-options-blocking-uri-value="" data-bluesky-options-own-value="false" data-bluesky-options-delete-url-value="" data-bluesky-options-post-element-selector-value='[data-card-type="bsky-post"]'> <button type="button" class="inline-flex items-center" data-action="click->bluesky-options#toggleMenu" aria-label="Post options"> <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="1"/><circle cx="19" cy="12" r="1"/><circle cx="5" cy="12" r="1"/></svg> </button> <div class="hidden absolute right-0 bottom-full mb-3 w-60 rounded-2xl border border-white/10 bg-[#1C2333] text-white shadow-xl overflow-hidden" data-bluesky-options-target="menu"> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-options#translate"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 4h16v16H4z"/><path d="M9 8h6"/><path d="M9 12h6"/><path d="M9 16h6"/></svg> </span> <span>Translate</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-options#copyText"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="8" y="8" width="12" height="12" rx="2"/><path d="M16 8V6a2 2 0 0 0-2-2h-8a2 2 0 0 0-2 2v8"/></svg> </span> <span>Copy post text</span> </button> <div class="border-t border-white/10"></div> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-options#muteAccount"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 9v6h3l5 5V4L7 9H4z"/><line x1="16" y1="9" x2="19" y2="12"/><line x1="19" y1="12" x2="16" y2="15"/></svg> </span> <span data-bluesky-options-target="muteLabel">Mute account</span> </button> <button type="button" class="w-full px-4 py-3 flex items-center gap-3 text-sm hover:bg-[#273045] text-left" data-action="click->bluesky-auth#requireConnection click->bluesky-options#blockAccount"> <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10"> <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 3h18v18H3z"/><path d="M3 3l18 18"/></svg> </span> <span data-bluesky-options-target="blockLabel">Block account</span> </button> </div> </div> </div> </div> </div> </div> </div> </div> <script> // Prevent navigation when clicking in avatar column area - must run in capture phase before global handler // Only initialize once to avoid duplicate listeners if (!window._avatarColumnNoNavInitialized) { window._avatarColumnNoNavInitialized = true; document.addEventListener('click', function(ev) { try { // Check if target itself has the class OR is inside an element with that class var avatarColumn = (ev.target.classList && ev.target.classList.contains('avatar-column-no-nav')) || (ev.target.closest && ev.target.closest('.avatar-column-no-nav')); if (avatarColumn) { // Only allow navigation if clicking directly on the avatar link itself var isAvatarLink = ev.target.tagName === 'A' && ev.target.href && ev.target.href.indexOf('/author') !== -1; if (!isAvatarLink) { ev.stopPropagation(); ev.stopImmediatePropagation(); ev.preventDefault(); return false; } } } catch(e) {} }, true); // Capture phase - runs BEFORE other handlers } </script> </div> </div> </div> </main> <!-- mobile footer CTA will be rendered after the grid to avoid stacking issues --> </div> <div class="hidden md:block"></div> </div> <!-- Mobile footer: CTA when logged out; mini-nav when logged in --> <div id="cta-footer" class="md:hidden fixed bottom-0 left-0 right-0 z-40 bg-white dark:bg-black border-t border-gray-200 dark:border-gray-700"> <div class="px-2 pt-3 pb-5"> <div class="flex items-center justify-between gap-3"> <!-- Left: Logo + Text --> <div class="flex items-center gap-2 flex-1 min-w-0"> <a class="inline-flex items-center gap-2" aria-label="Lightnews" data-apply-edition="1" href="/"> <img alt="Lightnews" class="logo-light h-10 w-10 flex-shrink-0" src="/assets/lightnews_black-993b5cbd.png" /> <img alt="Lightnews" class="logo-dark h-10 w-10 flex-shrink-0" src="/assets/lightnews-f13a19bd.png" /> <span class="text-base font-semibold text-gray-900 dark:text-white truncate brand-text">Lightnews</span> </a> </div> <!-- Right: Buttons --> <div class="flex items-center gap-2 flex-shrink-0"> <button type="button" data-action="click->bluesky-auth#openOAuthModal" class="btn btn-primary btn-sm whitespace-nowrap">Create account</button> <button type="button" data-action="click->bluesky-auth#openOAuthModal" class="btn btn-light btn-sm whitespace-nowrap">Sign in</button> </div> </div> </div> </div> <!-- Add bottom padding to body on mobile to prevent content from being hidden behind sticky footer --> <style> @media (max-width: 767px) { body { padding-bottom: 6.5rem; } } /* Hard guarantee: footer is visible on mobile widths */ @media (max-width: 1023px) { #cta-footer { display: block !important; } } </style> <!-- Sign In Modal --> <div id="signin-modal" class="hidden fixed inset-0 z-50 overflow-y-auto" data-auth-modal-target="signinModal"> <div class="flex min-h-screen items-center justify-center p-4"> <!-- Backdrop --> <div class="fixed inset-0 bg-black/80 transition-opacity" data-action="click->auth-modal#close"></div> <!-- Modal Content --> <div class="relative bg-white dark:bg-black rounded-2xl w-full max-w-md p-8 shadow-2xl"> <!-- Close Button --> <button data-action="click->auth-modal#close" class="absolute top-4 right-4 text-gray-400 hover:text-white transition-colors"> <svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="18" y1="6" x2="6" y2="18"></line> <line x1="6" y1="6" x2="18" y2="18"></line> </svg> </button> <!-- Logo --> <div class="flex justify-center mb-6"> <img alt="Lightnews" class="logo-light h-12 w-12" src="/assets/lightnews_black-993b5cbd.png" /> <img alt="Lightnews" class="logo-dark h-12 w-12" src="/assets/lightnews-f13a19bd.png" /> </div> <!-- Title --> <h2 class="text-black dark:text-white text-3xl font-bold text-center mb-6">Sign in to Lightnews</h2> <!-- Top CTA: Bluesky quick sign-in (neutral OAuth style with icon) --> <div class="mb-6"> <a class="w-full flex items-center justify-center gap-3 px-6 py-3 bg-transparent hover:bg-black/5 dark:hover:bg-white/10 text-black dark:text-white font-semibold rounded transition-colors border border-gray-300 dark:border-gray-600" data-turbo="false" href="/auth/bluesky/start"> <svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor"> <path d="M12 10.8c-1.087-2.114-4.046-6.053-6.798-7.995C2.566.944 1.561 1.266.902 1.565.139 1.908 0 3.08 0 3.768c0 .69.378 5.65.624 6.479.815 2.736 3.713 3.66 6.383 3.364.136-.02.275-.038.415-.056-.138.022-.276.04-.415.056-3.912.58-7.387 2.005-2.83 7.078 5.013 5.19 6.87-1.113 7.823-4.308.953 3.195 2.05 9.271 7.733 4.308 4.267-4.308 1.172-6.498-2.74-7.078a8.741 8.741 0 01-.415-.056c.14.018.279.036.415.056 2.67.297 5.568-.628 6.383-3.364.246-.828.624-5.79.624-6.478 0-.69-.139-1.861-.902-2.206-.659-.298-1.664-.62-4.3 1.24C16.046 4.748 13.087 8.687 12 10.8z" fill="#1185fe"/> </svg> Continue with Bluesky </a> </div> <!-- OAuth Buttons --> <div class="space-y-3 mb-6"> <!-- Google --> <button class="w-full flex items-center justify-center gap-3 px-6 py-3 bg-transparent hover:bg-black/5 dark:hover:bg-white/10 text-black dark:text-white font-semibold rounded transition-colors border border-gray-300 dark:border-gray-600"> <svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor"> <path d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z" fill="#4285F4"/> <path d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z" fill="#34A853"/> <path d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z" fill="#FBBC05"/> <path d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" fill="#EA4335"/> </svg> Continue with Google </button> <!-- Apple --> <button class="w-full flex items-center justify-center gap-3 px-6 py-3 bg-transparent hover:bg-black/5 dark:hover:bg-white/10 text-black dark:text-white font-semibold rounded transition-colors border border-gray-300 dark:border-gray-600"> <svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor"> <path d="M17.05 20.28c-.98.95-2.05.8-3.08.35-1.09-.46-2.09-.48-3.24 0-1.44.62-2.2.44-3.06-.35C2.79 15.25 3.51 7.59 9.05 7.31c1.35.07 2.29.74 3.08.8 1.18-.24 2.31-.93 3.57-.84 1.51.12 2.65.72 3.4 1.8-3.12 1.87-2.38 5.98.48 7.13-.57 1.5-1.31 2.99-2.54 4.09l.01-.01zM12.03 7.25c-.15-2.23 1.66-4.07 3.74-4.25.29 2.58-2.34 4.5-3.74 4.25z"/> </svg> Continue with Apple </button> </div> <!-- Divider --> <div class="relative my-6"> <div class="absolute inset-0 flex items-center"> <div class="w-full border-t border-gray-700"></div> </div> </div> <!-- Email Form --> <form class="space-y-4"> <div class="mt-10"> <label for="signin-email" class="block text-black dark:text-white font-semibold text-sm mb-2">Email or username</label> <input type="text" id="signin-email" placeholder="Email or username" class="w-full px-4 py-3 bg-gray-50 dark:bg-gray-900 border border-gray-300 dark:border-gray-700 rounded text-black dark:text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-blue-600 focus:border-transparent" /> </div> <button type="submit" class="w-full btn btn-primary py-3 font-semibold"> Continue </button> </form> <!-- Footer --> <div class="mt-8 text-center"> <p class="text-gray-600 dark:text-gray-400 mb-2">Don't have an account?</p> <button data-action="click->auth-modal#switchToSignup" class="text-blue-600 dark:text-white font-semibold underline hover:text-blue-500 transition-colors"> Sign up for Lightnews </button> </div> </div> </div> </div> <!-- Sign Up Modal --> <div id="signup-modal" class="hidden fixed inset-0 z-50 overflow-y-auto" data-auth-modal-target="signupModal"> <div class="flex min-h-screen items-center justify-center p-4"> <!-- Backdrop --> <div class="fixed inset-0 bg-black/80 transition-opacity" data-action="click->auth-modal#close"></div> <!-- Modal Content --> <div class="relative bg-white dark:bg-black rounded-2xl w-full max-w-md p-8 shadow-2xl"> <!-- Close Button --> <button data-action="click->auth-modal#close" class="absolute top-4 right-4 text-gray-400 hover:text-white transition-colors"> <svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="18" y1="6" x2="6" y2="18"></line> <line x1="6" y1="6" x2="18" y2="18"></line> </svg> </button> <!-- Logo --> <div class="flex justify-center mb-6"> <img alt="Lightnews" class="logo-light h-12 w-12" src="/assets/lightnews_black-993b5cbd.png" /> <img alt="Lightnews" class="logo-dark h-12 w-12" src="/assets/lightnews-f13a19bd.png" /> </div> <!-- Title --> <h2 class="text-black dark:text-white text-3xl font-bold text-center mb-6">Sign up to start reading</h2> <!-- Top CTA: Bluesky quick sign-up (neutral OAuth style with icon) --> <div class="mb-6"> <a class="w-full flex items-center justify-center gap-3 px-6 py-3 bg-transparent hover:bg-black/5 dark:hover:bg-white/10 text-black dark:text-white font-semibold rounded transition-colors border border-gray-300 dark:border-gray-600" data-turbo="false" href="/auth/bluesky/start"> <svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor"> <path d="M12 10.8c-1.087-2.114-4.046-6.053-6.798-7.995C2.566.944 1.561 1.266.902 1.565.139 1.908 0 3.08 0 3.768c0 .69.378 5.65.624 6.479.815 2.736 3.713 3.66 6.383 3.364.136-.02.275-.038.415-.056-.138.022-.276.04-.415.056-3.912.58-7.387 2.005-2.83 7.078 5.013 5.19 6.87-1.113 7.823-4.308.953 3.195 2.05 9.271 7.733 4.308 4.267-4.308 1.172-6.498-2.74-7.078a8.741 8.741 0 01-.415-.056c.14.018.279.036.415.056 2.67.297 5.568-.628 6.383-3.364.246-.828.624-5.79.624-6.478 0-.69-.139-1.861-.902-2.206-.659-.298-1.664-.62-4.3 1.24C16.046 4.748 13.087 8.687 12 10.8z" fill="#1185fe"/> </svg> Sign up with Bluesky </a> </div> <!-- Divider before email sign up --> <div class="relative my-4"> <div class="absolute inset-0 flex items-center"> <div class="w-full border-t border-gray-300 dark:border-gray-700"></div> </div> <div class="relative flex justify-center"> <span class="bg-white dark:bg-black px-3 text-sm text-gray-600 dark:text-gray-300">or</span> </div> </div> <!-- Email Form First --> <form class="space-y-4 mt-2"> <div> <label for="signup-email" class="block text-black dark:text-white font-semibold text-sm mt-2 mb-2">Email address</label> <input type="email" id="signup-email" placeholder="name@domain.com" class="w-full px-4 py-3 bg-gray-50 dark:bg-gray-900 border border-gray-300 dark:border-gray-700 rounded text-black dark:text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-blue-600 focus:border-transparent" /> </div> <button type="submit" class="w-full btn btn-primary py-3 font-semibold"> Next </button> </form> <!-- Divider --> <div class="relative my-6"> <div class="absolute inset-0 flex items-center"> <div class="w-full border-t border-gray-700"></div> </div> <div class="relative flex justify-center"> <span class="bg-white dark:bg-black px-4 text-black dark:text-white text-sm">or</span> </div> </div> <!-- OAuth Buttons --> <div class="space-y-3 mb-6"> <!-- Google --> <button class="w-full flex items-center justify-center gap-3 px-6 py-3 bg-transparent hover:bg-black/5 dark:hover:bg-white/10 text-black dark:text-white font-semibold rounded transition-colors border border-gray-300 dark:border-gray-600"> <svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor"> <path d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z" fill="#4285F4"/> <path d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z" fill="#34A853"/> <path d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z" fill="#FBBC05"/> <path d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" fill="#EA4335"/> </svg> Sign up with Google </button> <!-- Apple --> <button class="w-full flex items-center justify-center gap-3 px-6 py-3 bg-transparent hover:bg-black/5 dark:hover:bg-white/10 text-black dark:text-white font-semibold rounded transition-colors border border-gray-300 dark:border-gray-600"> <svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor"> <path d="M17.05 20.28c-.98.95-2.05.8-3.08.35-1.09-.46-2.09-.48-3.24 0-1.44.62-2.2.44-3.06-.35C2.79 15.25 3.51 7.59 9.05 7.31c1.35.07 2.29.74 3.08.8 1.18-.24 2.31-.93 3.57-.84 1.51.12 2.65.72 3.4 1.8-3.12 1.87-2.38 5.98.48 7.13-.57 1.5-1.31 2.99-2.54 4.09l.01-.01zM12.03 7.25c-.15-2.23 1.66-4.07 3.74-4.25.29 2.58-2.34 4.5-3.74 4.25z"/> </svg> Sign up with Apple </button> </div> <!-- Footer --> <div class="mt-8 text-center"> <p class="text-gray-600 dark:text-gray-400 mb-2">Already have an account?</p> <button data-action="click->auth-modal#switchToSignin" class="text-blue-600 dark:text-white font-semibold underline hover:text-blue-500 transition-colors"> Sign in </button> </div> </div> </div> </div> <div data-controller="modal" data-reply-modal="true" id="global-reply-modal" data-viewer-avatar-url="" data-viewer-display-name=""> <div class="hidden fixed inset-0 z-50 overflow-y-auto" data-modal-target="panel" data-viewer-avatar-url="" data-viewer-display-name=""> <div class="flex min-h-screen items-start justify-center pt-4 md:pt-20"> <!-- Backdrop --> <div class="fixed inset-0 bg-black/80 transition-opacity" data-action="click->modal#close"></div> <!-- Modal Content --> <div class="relative bg-[#1e3a5f] rounded-2xl w-full max-w-xl mx-4 shadow-2xl" data-action="click->modal#stop"> <!-- Top bar: Cancel + Reply button --> <div class="flex items-center justify-between px-4 py-3 border-b border-gray-600"> <button type="button" class="text-blue-400 text-base font-medium" data-action="click->modal#close">Cancel</button> <button type="button" id="modal-reply-submit" class="px-5 py-1.5 bg-blue-600 text-white rounded-full font-semibold hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed"> Reply </button> </div> <!-- Parent post preview (for replies) --> <div class="px-4 py-3 border-b border-gray-600 modal-reply-preview"> <div class="flex items-start gap-3"> <img src="" alt="" class="modal-reply-author-avatar w-10 h-10 rounded-full flex-shrink-0 hidden"> <div class="modal-reply-author-avatar-placeholder w-10 h-10 rounded-full bg-gray-300 flex-shrink-0"></div> <div class="flex-1 min-w-0"> <div class="font-semibold text-white text-base modal-reply-author-name"> </div> <div class="text-gray-300 text-sm line-clamp-3 modal-reply-post-text"> </div> </div> </div> </div> <!-- Reply/Post textarea --> <div class="px-4 py-3"> <div class="flex items-start gap-3"> <img src="" alt="You" class="modal-viewer-avatar w-10 h-10 rounded-full flex-shrink-0 hidden"> <div class="modal-viewer-avatar-placeholder w-10 h-10 rounded-full bg-gray-300 flex-shrink-0 "></div> <div class="flex-1 min-w-0"> <textarea id="modal-reply-text" placeholder="Write your reply" rows="8" maxlength="300" class="w-full px-0 py-2 bg-transparent text-white text-base placeholder-gray-400 resize-none focus:outline-none border-0" data-reply-uri="" data-reply-cid="" data-root-uri="" data-root-cid="" data-mode="reply" data-embed="" ></textarea> </div> </div> <!-- Quote preview (for quote posts, shown below textarea) --> <div class="modal-quote-preview hidden mt-3 p-3 border border-gray-600 rounded-xl bg-[#152642]"> <div class="flex items-start gap-3"> <img src="" alt="" class="modal-quote-author-avatar w-8 h-8 rounded-full flex-shrink-0 hidden"> <div class="modal-quote-author-avatar-placeholder w-8 h-8 rounded-full bg-gray-400 flex-shrink-0"></div> <div class="flex-1 min-w-0"> <div class="font-semibold text-white text-sm modal-quote-author-name"></div> <div class="text-gray-300 text-sm mt-1 modal-quote-post-text"></div> </div> </div> </div> <input type="file" id="modal-attachment-input" accept="image/*" class="hidden" multiple> <div id="modal-attachment-preview" class="mt-3 hidden"> <div class="flex flex-wrap gap-3" id="modal-attachment-preview-list"></div> </div> </div> <!-- Bottom toolbar --> <div class="px-4 py-3 border-t border-gray-600 flex items-center justify-between"> <div class="flex items-center gap-3"> <button type="button" class="text-blue-500 hover:text-blue-400" id="modal-attachment-button"> <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg> </button> <button type="button" class="text-blue-500 hover:text-blue-400" id="modal-gif-button"> <svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor"><text x="3" y="18" font-family="Arial" font-size="14" font-weight="bold">GIF</text></svg> </button> </div> <div class="flex items-center gap-3 text-sm"> <span class="text-blue-400">English</span> <span class="text-gray-400" id="modal-reply-count">300</span> </div> </div> </div> </div> </div> </div> <script> (function(){ function setupReplyModal(){ var textarea = document.getElementById('modal-reply-text'); var submitBtn = document.getElementById('modal-reply-submit'); var countEl = document.getElementById('modal-reply-count'); var attachmentButton = document.getElementById('modal-attachment-button'); var gifButton = document.getElementById('modal-gif-button'); var attachmentInput = document.getElementById('modal-attachment-input'); var attachmentPreview = document.getElementById('modal-attachment-preview'); var attachmentList = document.getElementById('modal-attachment-preview-list'); if (!textarea || !submitBtn || !countEl) { return; } if (textarea.dataset.replyModalBound === '1') { return; } textarea.dataset.replyModalBound = '1'; var attachments = []; var currentEmbed = null; var isUploadingAttachment = false; var MAX_ATTACHMENTS = 4; function updateCount(){ var length = textarea.value.length; var remaining = 300 - length; countEl.textContent = remaining.toString(); countEl.classList.toggle('text-red-400', remaining < 0); countEl.classList.toggle('text-gray-400', remaining >= 0); submitBtn.disabled = ((length === 0) && attachments.length === 0) || length > 300; } function updateEmbedPayload() { if (!attachments.length) { currentEmbed = null; textarea.removeAttribute('data-embed'); return; } currentEmbed = { "$type": "app.bsky.embed.images", "images": attachments.map(function(item){ return { "alt": item.alt || 'Image', "image": item.blob }; }) }; textarea.dataset.embed = JSON.stringify(currentEmbed); } function refreshAttachmentPreview() { if (!attachmentList || !attachmentPreview) { return; } attachmentList.innerHTML = ''; attachments.forEach(function(item, index){ var wrapper = document.createElement('div'); wrapper.className = 'relative w-20 h-20 rounded-xl overflow-hidden'; var img = document.createElement('img'); img.src = item.previewUrl; img.alt = item.alt || 'Attachment'; img.className = 'object-cover w-full h-full'; wrapper.appendChild(img); var removeBtn = document.createElement('button'); removeBtn.type = 'button'; removeBtn.className = 'absolute top-1 right-1 bg-black/70 text-white rounded-full w-6 h-6 flex items-center justify-center text-xs'; removeBtn.innerHTML = '×'; removeBtn.addEventListener('click', function(){ removeAttachment(index); }); wrapper.appendChild(removeBtn); attachmentList.appendChild(wrapper); }); if (attachments.length) { attachmentPreview.classList.remove('hidden'); } else { attachmentPreview.classList.add('hidden'); } if (attachmentButton) { attachmentButton.disabled = attachments.length >= MAX_ATTACHMENTS || isUploadingAttachment; attachmentButton.classList.toggle('opacity-50', attachmentButton.disabled); attachmentButton.classList.toggle('pointer-events-none', attachmentButton.disabled); } if (gifButton) { gifButton.disabled = attachments.length >= MAX_ATTACHMENTS || isUploadingAttachment; gifButton.classList.toggle('opacity-50', gifButton.disabled); gifButton.classList.toggle('pointer-events-none', gifButton.disabled); } updateCount(); } function removeAttachment(index) { if (index < 0 || index >= attachments.length) { return; } var removed = attachments.splice(index, 1)[0]; if (removed && removed.previewUrl) { try { URL.revokeObjectURL(removed.previewUrl); } catch (_) {} } updateEmbedPayload(); refreshAttachmentPreview(); } function setAttachmentUploading(state) { isUploadingAttachment = state; refreshAttachmentPreview(); } async function uploadFile(file) { if (!file || !attachmentInput) { return; } if (!file.type.match(/^image\//)) { alert('Only image uploads are supported right now.'); return; } if (attachments.length >= MAX_ATTACHMENTS) { alert('You can attach up to ' + MAX_ATTACHMENTS + ' images.'); return; } if (file.size > 976 * 1024) { alert('Images must be 976KB or smaller.'); return; } setAttachmentUploading(true); var formData = new FormData(); formData.append('file', file); formData.append('alt', file.name || 'Image'); try { var response = await fetch('/api/bluesky/uploads', { method: 'POST', headers: { 'X-CSRF-Token': (document.querySelector('meta[name="csrf-token"]') || {}).content || '', 'Accept': 'application/json' }, credentials: 'same-origin', body: formData }); if (!response.ok) { var errorText = await response.text(); var message = 'Upload failed'; try { var parsed = JSON.parse(errorText); message = parsed.error || message; } catch (_) { if (errorText && errorText.length < 200) { message = errorText; } } throw new Error(message); } var data = await response.json(); if (!data || !data.success || !data.blob) { throw new Error((data && data.error) || 'Upload failed'); } var previewUrl = URL.createObjectURL(file); attachments.push({ blob: data.blob, alt: data.alt || file.name || 'Image', previewUrl: previewUrl }); updateEmbedPayload(); refreshAttachmentPreview(); } catch (error) { console.error('Attachment upload error:', error); alert(error && error.message ? error.message : 'Unable to upload image right now.'); } finally { setAttachmentUploading(false); if (attachmentInput) { attachmentInput.value = ''; } } } function handleFileSelection(files) { if (!files || !files.length) { return; } var remaining = MAX_ATTACHMENTS - attachments.length; Array.from(files).slice(0, remaining).forEach(function(file){ uploadFile(file); }); } if (attachmentButton && attachmentInput) { attachmentButton.addEventListener('click', function(e){ e.preventDefault(); if (isUploadingAttachment || attachments.length >= MAX_ATTACHMENTS) { return; } attachmentInput.setAttribute('accept', 'image/*'); attachmentInput.click(); }); } if (gifButton && attachmentInput) { gifButton.addEventListener('click', function(e){ e.preventDefault(); if (isUploadingAttachment || attachments.length >= MAX_ATTACHMENTS) { return; } attachmentInput.setAttribute('accept', 'image/gif'); attachmentInput.click(); }); } if (attachmentInput) { attachmentInput.addEventListener('change', function(e){ handleFileSelection(e.target.files); }); } refreshAttachmentPreview(); textarea.addEventListener('input', updateCount); updateCount(); submitBtn.addEventListener('click', async function(e){ e.preventDefault(); var text = textarea.value.trim(); if ((text.length === 0 && attachments.length === 0) || text.length > 300) { return; } var replyUri = textarea.dataset.replyUri; var replyCid = textarea.dataset.replyCid; var rootUri = textarea.dataset.rootUri; var rootCid = textarea.dataset.rootCid; var mode = textarea.dataset.mode || 'reply'; if (mode === 'reply' && (!replyUri || !replyCid)) { return; } submitBtn.disabled = true; var originalText = submitBtn.textContent; submitBtn.textContent = mode === 'post' ? 'Posting...' : 'Replying...'; try { var endpoint, payload; if (mode === 'post') { endpoint = '/api/bluesky/posts'; payload = { text: text }; } else { endpoint = '/api/bluesky/replies'; payload = { text: text, reply_to_uri: replyUri, reply_to_cid: replyCid, root_uri: rootUri, root_cid: rootCid }; } // Attach quote embed if present (for quote posts) - check first var quoteEmbed = textarea.dataset.quoteEmbed; if (quoteEmbed && mode === 'post' && !currentEmbed) { try { payload.embed = JSON.parse(quoteEmbed); console.log('Added quote embed:', payload.embed); } catch (e) { console.error('Failed to parse quote embed', e); } } // Attach image embed if present (overrides quote for now) if (currentEmbed) { payload.embed = currentEmbed; console.log('Added image embed:', payload.embed); } console.log('Submitting payload:', JSON.stringify(payload).substring(0, 300)); var response = await fetch(endpoint, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': (document.querySelector('meta[name="csrf-token"]') || {}).content || '' }, credentials: 'same-origin', body: JSON.stringify(payload) }); console.log('Reply response status:', response.status); if (!response.ok) { var errorText = await response.text(); var errorMessage = 'Network error. Please try again.'; var settingsUrl = null; try { var errorData = JSON.parse(errorText); errorMessage = errorData.error || errorMessage; settingsUrl = errorData.settings_url || null; } catch (e2) { if (errorText && errorText.length < 200) { errorMessage = errorText; } else { errorMessage = 'HTTP ' + response.status + ': ' + response.statusText; } } console.error('Error response:', response.status, errorMessage); if (response.status === 401 && settingsUrl) { if (confirm(errorMessage + '\n\nWould you like to go to Settings now?')) { window.location.href = settingsUrl; return; } } else { alert(errorMessage); } submitBtn.disabled = false; submitBtn.textContent = originalText; return; } var data = await response.json(); console.log('Reply response data:', data); if (data.success) { window.location.reload(); } else { alert(data.error || (mode === 'post' ? 'Failed to create post' : 'Failed to post reply')); submitBtn.disabled = false; submitBtn.textContent = originalText; } } catch (error) { console.error('Reply error:', error); alert(error && error.message ? error.message : 'Network error. Please try again.'); submitBtn.disabled = false; submitBtn.textContent = originalText; } }); } function openReplyIfRequested(){ try{ var qs = new URLSearchParams(window.location.search); if(qs.get('reply') === '1'){ var panel = document.querySelector('[data-modal-target="panel"]'); if(panel){ panel.classList.remove('hidden'); document.documentElement.classList.add('overflow-hidden'); document.body.classList.add('overflow-hidden'); var ta = document.getElementById('modal-reply-text'); if(ta){ ta.focus(); } } } }catch(e){} } function initReplyModal(){ setupReplyModal(); openReplyIfRequested(); } document.addEventListener('turbo:load', function(){ setTimeout(initReplyModal, 0); }); if (document.readyState === 'complete' || document.readyState === 'interactive') { setTimeout(initReplyModal, 0); } else { document.addEventListener('DOMContentLoaded', initReplyModal); } })(); </script> <script> // Sanitize any legacy nav=1 param from links and the current URL document.addEventListener('click', function(ev){ try{ var a = ev.target.closest && ev.target.closest('a'); if(!a) return; var url = new URL(a.href, location.origin); if(url.searchParams.has('nav')){ url.searchParams.delete('nav'); a.setAttribute('href', url.pathname + (url.searchParams.toString() ? ('?' + url.searchParams.toString()) : '') + url.hash); } }catch(e){} }, true); document.addEventListener('turbo:load', function(){ try{ var url = new URL(location.href); if(url.searchParams.has('nav')){ url.searchParams.delete('nav'); var cleaned = url.pathname + (url.searchParams.toString() ? ('?' + url.searchParams.toString()) : '') + url.hash; history.replaceState(null, '', cleaned); } }catch(e){} }); </script> <script> function loadTwitterEmbeds() { try { if (window.twttr && window.twttr.widgets) { window.twttr.widgets.load(); return true; } } catch(e) {} return false; } document.addEventListener("turbo:load", function() { if (!loadTwitterEmbeds()) { var tries = 0; var max = 10; (function retry(){ if (loadTwitterEmbeds() || ++tries > max) return; setTimeout(retry, 400); })(); } // Re-hydrate Bluesky embeds after Turbo navigation by reinjecting the script try { var s = document.createElement("script"); s.src = "https://embed.bsky.app/static/embed.js?ts=" + Date.now(); s.async = true; s.onload = function(){ try { s.remove(); } catch(_){} }; document.body.appendChild(s); } catch (e) {} }); </script> <script> // Decorate links to lists (home/sections) with stored edition at click time (web only) document.addEventListener('click', function(ev){ try{ var a = ev.target.closest && ev.target.closest('a[data-apply-edition="1"]'); if(!a) return; var pref = localStorage.getItem('preferredEdition'); if(pref && pref !== 'global'){ var url = new URL(a.href, location.origin); url.searchParams.set('edition', pref); if (url.toString() !== a.href) { // Update href and let the browser/Turbo handle the navigation once a.setAttribute('href', url.pathname + '?' + url.searchParams.toString() + url.hash); } } else { var url2 = new URL(a.href, location.origin); if(url2.searchParams.has('edition')){ url2.searchParams.delete('edition'); var newHref = url2.pathname + (url2.searchParams.toString() ? ('?' + url2.searchParams.toString()) : '') + url2.hash; a.setAttribute('href', newHref); } } }catch(e){} }, true); </script> <script> // Track last list path (home or sections) for back navigation on digest pages document.addEventListener('turbo:load', function(){ try{ var path = location.pathname; if(path === '/' || path.indexOf('/sections/') === 0){ var url = new URL(location.href); var ed = url.searchParams.get('edition'); var stored = path + (ed ? ('?edition=' + ed) : ''); sessionStorage.setItem('lastListPath', stored); sessionStorage.setItem('lastNonPost', stored); } else if(path === '/trending'){ sessionStorage.setItem('lastTrendingPath', '/trending'); sessionStorage.setItem('lastNonPost', '/trending'); } else if(path.indexOf('/digests/') === 0){ // Keep lastDigestPath fresh when on digest pages to avoid stale fallbacks sessionStorage.setItem('lastDigestPath', path + location.search); sessionStorage.setItem('lastNonPost', path + location.search); } }catch(e){} }); </script> <script> // Remove any l=... language parameter from digest links to unify cache keys document.addEventListener('click', function(ev){ try{ var a = ev.target.closest && ev.target.closest('a[href^="/digests/"]'); if(!a) return; var url = new URL(a.href, location.origin); if(url.searchParams.has('l')){ url.searchParams.delete('l'); var newHref = url.pathname + (url.searchParams.toString() ? ('?' + url.searchParams.toString()) : '') + url.hash; a.setAttribute('href', newHref); } }catch(e){} }, true); </script> <script> // Remember previous page before navigating to a local Bluesky post via anchor document.addEventListener('click', function(ev){ try{ var a = ev.target.closest && ev.target.closest('a[href^="/bsky/"]'); if(!a) return; var prev = location.pathname + location.search; sessionStorage.setItem('prevPage', prev); sessionStorage.setItem('lastPostPath', location.pathname); }catch(e){} }, true); </script> <script> // Remember previous page before navigating to an author profile document.addEventListener('click', function(ev){ try{ // Match both /author and /author/... and /author?... var a = ev.target.closest && (ev.target.closest('a[href^="/author/"]') || ev.target.closest('a[href^="/author"]')); if(!a) return; var prev = location.pathname + location.search; sessionStorage.setItem('prevPage', prev); if(location.pathname.indexOf('/author/') !== 0){ sessionStorage.setItem('lastNonAuthor', prev); } sessionStorage.setItem('entrySource','author'); }catch(e){} }, true); </script> <script> // Also sanitize card-clickable data-href: strip l=... if present document.addEventListener('click', function(ev){ try{ var card = ev.target.closest && ev.target.closest('.card-clickable'); if(!card) return; var href = (card.getAttribute('data-href') || '').trim(); if(!href) return; // Strip accidental wrapping quotes if((href[0]==='"' && href[href.length-1]==='"') || (href[0]==="'" && href[href.length-1]==="'")){ href = href.slice(1,-1); } var url = new URL(href, location.origin); if(url.searchParams.has('l')){ url.searchParams.delete('l'); var newHref = url.pathname + (url.searchParams.toString() ? ('?' + url.searchParams.toString()) : '') + url.hash; card.setAttribute('data-href', newHref); } // Navigate on card click unless clicking an inner actionable link var isInlineVideo = ev.target.closest && ev.target.closest('.inline-video'); // Tag nested-card navigations so back button can return to previous post instead of thread parent var inNested = ev.target.closest && ev.target.closest('.bsky-nested, .nested-bsky, .bluesky-nested'); // Don't navigate if clicking in avatar column area (left side of post with avatar and thread lines) // Check if target itself has the class OR is inside an element with that class var isAvatarColumn = (ev.target.classList && ev.target.classList.contains('avatar-column-no-nav')) || (ev.target.closest && ev.target.closest('.avatar-column-no-nav')); if(!ev.target.closest('.no-card-link') && !isInlineVideo && !isAvatarColumn){ ev.preventDefault(); var targetHref = (card.getAttribute('data-href') || href).trim(); if((targetHref[0]==='"' && targetHref[targetHref.length-1]==='"') || (targetHref[0]==="'" && targetHref[targetHref.length-1]==="'")){ targetHref = targetHref.slice(1,-1); } try{ // If navigating from a digest page to a post, remember this digest for back navigation if(location.pathname.indexOf('/digests/') === 0){ sessionStorage.setItem('lastDigestPath', location.pathname + location.search); sessionStorage.setItem('entrySource','digest'); } else if(location.pathname.indexOf('/bsky/') === 0){ // Navigating from a post to another post (e.g., reply): mark source as post sessionStorage.setItem('entrySource', inNested ? 'nested' : 'post'); } // Always remember the immediate previous page when going to a post if(targetHref.indexOf('/bsky/') === 0){ var prevp = location.pathname + location.search; sessionStorage.setItem('prevPage', prevp); sessionStorage.setItem('lastPostPath', location.pathname); } }catch(e){} if(window.Turbo && Turbo.visit){ Turbo.visit(targetHref); } else { window.location.href = targetHref; } } }catch(e){} }, true); </script> <script> // Keyboard activation for card-clickable elements document.addEventListener('keydown', function(ev){ try{ if(ev.key !== 'Enter' && ev.key !== ' ') return; var card = ev.target.closest && ev.target.closest('.card-clickable'); if(!card) return; var isInlineVideo = ev.target.closest && ev.target.closest('.inline-video'); if(isInlineVideo) return; var href = (card.getAttribute('data-href') || '').trim(); if(!href) return; if((href[0]==='"' && href[href.length-1]==='"') || (href[0]==="'" && href[href.length-1]==="'")){ href = href.slice(1,-1); } ev.preventDefault(); if(window.Turbo && Turbo.visit){ Turbo.visit(href); } else { window.location.href = href; } }catch(e){} }, true); </script> <script> // Sync stored edition from current URL on list pages (no navigation) // Only update when the URL explicitly includes an edition param; otherwise keep prior preference. document.addEventListener("turbo:load", function(){ try{ var onDigest = location.pathname.indexOf('/digests/') === 0; if(onDigest) return; var url = new URL(location.href); if(url.searchParams.has('edition')){ var ed = url.searchParams.get('edition'); localStorage.setItem('preferredEdition', (ed && ed !== 'global') ? ed : 'global'); } }catch(e){} }); </script> <div data-controller="modal" data-bluesky-auth-target="modal" id="bluesky-pds-modal"> <div class="hidden fixed inset-0 z-50 overflow-y-auto" data-modal-target="panel"> <div class="flex min-h-screen items-center justify-center p-4"> <div class="fixed inset-0 bg-black/80 transition-opacity" data-action="click->modal#close"></div> <div class="relative bg-white dark:bg-black rounded-2xl w-full max-w-md p-8 shadow-2xl" data-action="click->modal#stop"> <button type="button" class="absolute top-4 right-4 text-gray-400 hover:text-black dark:hover:text-white transition" data-action="click->modal#close"> <svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="18" y1="6" x2="6" y2="18"></line> <line x1="6" y1="6" x2="18" y2="18"></line> </svg> </button> <div class="flex justify-center mb-6"> <img alt="Lightnews" class="logo-light h-12 w-12" src="/assets/lightnews_black-993b5cbd.png" /> <img alt="Lightnews" class="logo-dark h-12 w-12" src="/assets/lightnews-f13a19bd.png" /> </div> <h2 class="text-2xl font-bold text-center text-black dark:text-white mb-3">Connect Bluesky</h2> <p class="text-center text-sm text-gray-600 dark:text-gray-300 mb-6"> Enter your Bluesky handle and app password to unlock posting, likes, and your Following feed. </p> <div class="mb-4 hidden text-sm text-red-500" data-bluesky-auth-target="error"></div> <form data-bluesky-auth-target="form" class="space-y-4" action="/auth/bluesky/pds_session" accept-charset="UTF-8" method="post"><input type="hidden" name="authenticity_token" value="rDAU27pLGtx0nWCsUhCSfNU676c_LikKF_2ILygHtK1RK8tXy_2Dc7TV3JwG8tApVAiEAdDg_i2wUuxiRVIQvg" autocomplete="off" /> <div> <label class="block text-sm font-semibold text-black dark:text-white mb-2" for="identifier">Handle or email</label> <input placeholder="@you.bsky.social" autocomplete="username" required="required" class="w-full px-4 py-3 bg-gray-50 dark:bg-gray-900 border border-gray-300 dark:border-gray-700 rounded-lg text-black dark:text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-blue-600 focus:border-transparent" data-bluesky-auth-target="identifierInput" type="text" name="identifier" id="identifier" /> </div> <div> <label class="block text-sm font-semibold text-black dark:text-white mb-2" for="password">App password</label> <input placeholder="xxxx-xxxx-xxxx-xxxx" autocomplete="current-password" required="required" class="w-full px-4 py-3 bg-gray-50 dark:bg-gray-900 border border-gray-300 dark:border-gray-700 rounded-lg text-black dark:text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-blue-600 focus:border-transparent" data-bluesky-auth-target="passwordInput" type="password" name="password" id="password" /> </div> <div class="hidden" data-bluesky-auth-target="tfaField"> <label class="block text-sm font-semibold text-black dark:text-white mb-2" for="auth_factor_token">2FA Code</label> <input placeholder="123456" autocomplete="one-time-code" inputmode="numeric" pattern="[0-9]*" class="w-full px-4 py-3 bg-gray-50 dark:bg-gray-900 border border-gray-300 dark:border-gray-700 rounded-lg text-black dark:text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-blue-600 focus:border-transparent" data-bluesky-auth-target="tfaInput" type="text" name="auth_factor_token" id="auth_factor_token" /> </div> <button type="submit" class="w-full btn btn-primary py-3 font-semibold" data-bluesky-auth-target="submitButton"> Connect Bluesky </button> </form> <p class="mt-5 text-xs text-center text-gray-500 dark:text-gray-400"> Need an app password? Open Bluesky, go to Settings > App passwords, and create a new one. </p> </div> </div> </div> </div> <!-- Bluesky OAuth Modal - Shows when logged-out user tries Bluesky action --> <div id="bluesky-oauth-modal" class="hidden fixed inset-0 z-50 overflow-y-auto" data-bluesky-auth-target="oauthModal"> <div class="flex min-h-screen items-center justify-center p-4"> <!-- Backdrop --> <div class="fixed inset-0 bg-black/80 transition-opacity" data-action="click->bluesky-auth#closeOAuthModal"></div> <!-- Modal Content --> <div class="relative bg-white dark:bg-black rounded-2xl w-full max-w-md p-8 shadow-2xl" data-action="click->bluesky-auth#stopPropagation"> <!-- Close Button --> <button data-action="click->bluesky-auth#closeOAuthModal" class="absolute top-4 right-4 text-gray-400 hover:text-white transition-colors"> <svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="18" y1="6" x2="6" y2="18"></line> <line x1="6" y1="6" x2="18" y2="18"></line> </svg> </button> <!-- Logo --> <div class="flex justify-center mb-6"> <img alt="Lightnews" class="logo-light h-12 w-12" src="/assets/lightnews_black-993b5cbd.png" /> <img alt="Lightnews" class="logo-dark h-12 w-12" src="/assets/lightnews-f13a19bd.png" /> </div> <!-- Title --> <h2 class="text-black dark:text-white text-3xl font-bold text-center mb-3">Connect with Bluesky</h2> <!-- Description --> <p class="text-center text-base text-gray-600 dark:text-gray-300 mb-6"> Sign in with your Bluesky account to unlock posting, likes, and your Following feed. </p> <!-- Buttons --> <div class="space-y-3"> <!-- Sign In Button - Grey --> <button type="button" data-action="click->bluesky-auth#handleSignIn" data-bluesky-auth-target="signinButton" class="bsky-signin-btn w-full flex items-center justify-center gap-3 px-6 py-3 bg-gray-600 hover:bg-gray-700 font-semibold rounded transition-colors border border-gray-600 text-white"> <svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor" style="color: #1185fe !important;"> <path d="M12 10.8c-1.087-2.114-4.046-6.053-6.798-7.995C2.566.944 1.561 1.266.902 1.565.139 1.908 0 3.08 0 3.768c0 .69.378 5.65.624 6.479.815 2.736 3.713 3.66 6.383 3.364.136-.02.275-.038.415-.056-.138.022-.276.04-.415.056-3.912.58-7.387 2.005-2.83 7.078 5.013 5.19 6.87-1.113 7.823-4.308.953 3.195 2.05 9.271 7.733 4.308 4.267-4.308 1.172-6.498-2.74-7.078a8.741 8.741 0 01-.415-.056c.14.018.279.036.415.056 2.67.297 5.568-.628 6.383-3.364.246-.828.624-5.79.624-6.478 0-.69-.139-1.861-.902-2.206-.659-.298-1.664-.62-4.3 1.24C16.046 4.748 13.087 8.687 12 10.8z" fill="#1185fe"/> </svg> <span>Sign in</span> </button> <!-- Create Account Button - Blue --> <button type="button" data-action="click->bluesky-auth#handleCreateAccount" data-bluesky-auth-target="signupButton" class="bsky-signup-btn w-full flex items-center justify-center gap-3 px-6 py-3 bg-blue-600 hover:bg-blue-700 font-semibold rounded transition-colors border border-blue-600" style="color: #ffffff !important;"> <svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor" style="color: #ffffff !important;"> <path d="M12 10.8c-1.087-2.114-4.046-6.053-6.798-7.995C2.566.944 1.561 1.266.902 1.565.139 1.908 0 3.08 0 3.768c0 .69.378 5.65.624 6.479.815 2.736 3.713 3.66 6.383 3.364.136-.02.275-.038.415-.056-.138.022-.276.04-.415.056-3.912.58-7.387 2.005-2.83 7.078 5.013 5.19 6.87-1.113 7.823-4.308.953 3.195 2.05 9.271 7.733 4.308 4.267-4.308 1.172-6.498-2.74-7.078a8.741 8.741 0 01-.415-.056c.14.018.279.036.415.056 2.67.297 5.568-.628 6.383-3.364.246-.828.624-5.79.624-6.478 0-.69-.139-1.861-.902-2.206-.659-.298-1.664-.62-4.3 1.24C16.046 4.748 13.087 8.687 12 10.8z" fill="currentColor"/> </svg> <span style="color: #ffffff !important;">Create an account</span> </button> </div> </div> </div> </div> </body> </html>