Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/quarterback/dev-site. dev-site-five-kappa.vercel.app
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><link rel="icon" href="/favicon.svg" type="image/svg+xml" /><link rel="icon" href="/favicon.png" type="image/png" sizes="any" /><title>Glowrm | Ron Bronson</title><meta name="description" content="Trust infrastructure for ATProto social applications. Apps plug in for cross-app reputation, shared moderation, and a configurable resource-allocation system, so apps share one set of trust plumbing." /><link rel="canonical" href="https://ronbronson.dev/projects/glowrm.html" /><meta property="og:type" content="website" /><meta property="og:site_name" content="Ron Bronson" /><meta property="og:title" content="Glowrm | Ron Bronson" /><meta property="og:description" content="Trust infrastructure for ATProto social applications. Apps plug in for cross-app reputation, shared moderation, and a configurable resource-allocation system, so apps share one set of trust plumbing." /><meta property="og:url" content="https://ronbronson.dev/projects/glowrm.html" /><meta property="og:image" content="https://ronbronson.dev/assets/social-card.png" /><meta property="og:image:width" content="1200" /><meta property="og:image:height" content="630" /><meta property="og:image:alt" content="Ron Bronson beside the words Problems Are Designed, with a workshop photo and a content schema check." /><meta name="twitter:card" content="summary_large_image" /><meta name="twitter:title" content="Glowrm | Ron Bronson" /><meta name="twitter:description" content="Trust infrastructure for ATProto social applications. Apps plug in for cross-app reputation, shared moderation, and a configurable resource-allocation system, so apps share one set of trust plumbing." /><meta name="twitter:image" content="https://ronbronson.dev/assets/social-card.png" /><link rel="preload" as="font" type="font/woff2" href="../assets/fonts/gallery/PPNeueMontreal-Extrabold.woff2" crossorigin /><!-- standard.site --><link rel="site.standard.document" href="at://did:plc:odgxwakrg5r2zjetnrkxuh5c/site.standard.document/3mpfibvgphz2j" /><!-- /standard.site --><link rel="stylesheet" href="../assets/slabs.css" /><script src="../assets/contact.js" defer></script></head><body class="pg-blue"><div class="s-wrap">
<header class="top"> <p class="top__name"><a href="../index.html">Ron Bronson</a></p> <nav aria-label="Main navigation"><a href="../index.html#work">Work</a><a href="https://ronbronson.design">Design</a><a href="https://blog.ronbronson.dev">Blog</a><a class="nav-gh" href="https://github.com/quarterback" target="_blank" rel="me noopener" aria-label="GitHub" title="GitHub"><svg viewBox="0 0 496 512" width="22" height="22" fill="currentColor" aria-hidden="true"><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 26 31.4 26 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 82 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8z"/></svg></a><a class="nav-mail" href="#contact" data-contact aria-label="Email" title="Email"><svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linejoin="round" aria-hidden="true"><rect x="2.5" y="5" width="19" height="14"/><path d="M3 6l9 7 9-7"/></svg></a></nav> </header>
<article class="project">
<h1 class="project__title">Glowrm</h1> <p class="project__lede">Trust infrastructure for ATProto social applications. Apps plug in for cross-app reputation, shared moderation, and a configurable resource-allocation system, so apps share one set of trust plumbing.</p>
<div class="project__body">
<div class="pitch"> <span class="label">The pitch</span> Portable identity (ATProto) needs portable reputation, so Glowrm makes a user’s trust travel with them. </div>
<h2>What it does</h2>
<p>Dating apps, professional networks, and friendship platforms plug into Glowrm to share one reputation layer for trust and moderation.</p>
<ul> <li><b>Cross-app reputation.</b> User trust scores on a 20 to 80 scale that travel between apps. Good behavior on a dating app means you start with that same reputation on a professional network.</li> <li><b>Shared moderation.</b> When someone gets reported on one app, it affects their reputation across the network. Bad actors can’t platform-hop into a clean slate.</li> <li><b>Resource allocation (SPA).</b> A configurable system that caps how many people a user can contact per period. Each app picks its own units, count, and refresh cadence.</li> <li><b>Identity registry.</b> Maps ATProto DIDs to apps, tracks verification status, lets apps query each other’s coverage without storing each other’s user data.</li> </ul>
<h2>The problem it solves</h2>
<p>ATProto gives users portable identity: your DID and profile follow you across apps, you own your data, and no app can lock you in. The trade-off is that someone banned from one dating app can join another with a clean slate, and someone who harasses people can switch platforms and start fresh, so bad behavior carries no long-term consequences.</p>
<p>Traditional platforms solve this with centralized control. If Facebook bans you, you’re banned everywhere Facebook operates, and you’re also locked into Facebook’s ecosystem, which trades your freedom for safety.</p>
<p>Glowrm lets users move freely between apps while their reputation follows them.</p>
<h2>How it works in practice</h2>
<p>Trace what happens when two apps both speak Glowrm.</p>
<div class="flow"> <ol> <li><b>Alice signs into YGF</b> with ATProto. YGF tells Glowrm to register her DID. Glowrm creates an identity record, starts her reputation at <code>50</code>, and gives her fifteen jars for the week.</li> <li><b>Alice sends five jars to Bob.</b> YGF asks Glowrm to deduct five units. Balance: <code>10</code>.</li> <li><b>Bob and Alice match.</b> YGF reports a <code>positive_interaction</code>. Both reputations tick up by one.</li> <li><b>Alice reports Bob for harassment.</b> YGF posts a high-severity trust event. Bob’s reputation drops three points and the event flags for admin review.</li> <li><b>Bob is banned on YGF.</b> Admin issues a global ban through Glowrm. His reputation drops to <code>20</code>; his status becomes <code>banned</code>, network-wide.</li> <li><b>Bob tries to join Roster,</b> a professional network. Roster asks Glowrm to register his DID. Glowrm finds the existing identity, returns <code>{ reputation: 20, status: "banned" }</code>. Roster declines.</li> <li><b>Alice joins Roster.</b> Glowrm returns <code>{ reputation: 51, status: "active" }</code>. Roster shows her as a trusted user from day one.</li> </ol> <p class="key">Alice’s good behavior on YGF gave her a head start on Roster, Bob’s bad behavior kept him out, and Glowrm handled that coordination for both apps.</p> </div>
<h2>Reputation scores (20 to 80)</h2>
<p>The scale is borrowed from baseball scouting. <code>50</code> is average. Scores cluster around the middle; outliers at either extreme are rare and meaningful.</p>
<div class="rep-scale" role="table" aria-label="Reputation bands"> <div class="rep-scale__head"><span>Range</span><span>Band</span></div> <div class="rep-scale__row"><span class="range">70 to 80</span><span><span class="label">Exceptional.</span> <span class="desc">Consistently positive interactions; helpful, responsive.</span></span></div> <div class="rep-scale__row"><span class="range">60 to 69</span><span><span class="label">Above average.</span> <span class="desc">Good track record; few issues.</span></span></div> <div class="rep-scale__row"><span class="range">50 to 59</span><span><span class="label">Average.</span> <span class="desc">Normal range for a new or moderately active user.</span></span></div> <div class="rep-scale__row"><span class="range">40 to 49</span><span><span class="label">Below average.</span> <span class="desc">Some negative events; approaching problematic.</span></span></div> <div class="rep-scale__row"><span class="range">30 to 39</span><span><span class="label">Poor.</span> <span class="desc">Multiple reports, blocks, or suspicious patterns.</span></span></div> <div class="rep-scale__row"><span class="range">20 to 29</span><span><span class="label">Critical.</span> <span class="desc">Banned or serial bad actor.</span></span></div> </div>
<p>Scoring is designed to be hard to game. Multiple low scores are required to move a rating; outliers are dropped; recent events weigh more; reports from trusted users count for more.</p>
<h2>Trust events</h2>
<p>Every consequential interaction posts a trust event. The vocabulary is small on purpose.</p>
<table class="events"> <thead> <tr><th>Event</th><th>Impact</th></tr> </thead> <tbody> <tr><td>Positive interaction (match, conversation, completed transaction)</td><td>+1 (capped at +15 from this source)</td></tr> <tr><td>Report, low severity</td><td>−1</td></tr> <tr><td>Report, medium severity</td><td>−2</td></tr> <tr><td>Report, high severity</td><td>−3</td></tr> <tr><td>Block</td><td>−3</td></tr> <tr><td>Warn / suspend</td><td>weighted</td></tr> <tr><td>Ban</td><td>sets to 20</td></tr> </tbody> </table>
<h2>Strategic Profile Allocation (SPA)</h2>
<p>Unlimited actions invite spam: Tinder-style swiping defaults to spray-and-pray, and LinkedIn InMail turns into a fire hose of sales pitches. SPA fixes that at the infrastructure layer: every app issues users finite <i>units</i> per period, and recipients see how many units someone spent on them.</p>
<p>Each app configures its own SPA shape:</p>
<table class="spa"> <thead> <tr><th>App</th><th>Units</th><th>Name</th><th>Period</th><th>Variable?</th></tr> </thead> <tbody> <tr><td>YGF (dating)</td><td>15</td><td>jars</td><td>7 days</td><td>Yes (1 to 10)</td></tr> <tr><td>Roster (professional)</td><td>10</td><td>credits</td><td>30 days</td><td>Yes (1 to 5)</td></tr> <tr><td>Roomies (roommate)</td><td>20</td><td>waves</td><td>14 days</td><td>No (1 only)</td></tr> </tbody> </table>
<h2>Data separation</h2>
<p>Glowrm holds the trust layer and nothing else. Profile content lives in the user’s ATProto repo; conversations and matches live in the calling app’s database; Glowrm sees only DIDs, scores, events, and unit allocations.</p>
<dl class="stack-block"> <dt>Profile, photos, bio</dt> <dd>User’s ATProto repo · <i>user controls</i></dd> <dt>Messages, matches</dt> <dd>Calling app’s database · <i>app controls</i></dd> <dt>Reputation score</dt> <dd>Glowrm</dd> <dt>Trust events</dt> <dd>Glowrm</dd> <dt>Unit allocations</dt> <dd>Glowrm</dd> <dt>Verification status</dt> <dd>Glowrm</dd> </dl>
<p>No single store holds all of a user’s data: content belongs to the user, features to each app, and the shared trust layer to Glowrm.</p>
<h2>Reference implementations</h2>
<p>Three apps were sketched against the Glowrm API to show the delegation model end to end. Each picks its own SPA shape, with its own units, cadence, and rules, and all three use the same trust layer underneath.</p>
<div class="refs"> <div class="ref"> <div class="ref__type">Dating</div> <div class="ref__name">YGF</div> <div class="ref__spec"><b>15 jars / 7 days</b> · variable 1 to 10 · bilateral exchange unlocks messaging · recipients see what you spent.</div> </div> <div class="ref"> <div class="ref__type">Professional</div> <div class="ref__name">Roster</div> <div class="ref__spec"><b>10 credits / 30 days</b> · variable 1 to 5 · one credit = a quick question, five = a mentorship request.</div> <span style="font-family: var(--mono); font-size: 12px; color: var(--ink-soft);">Spec only</span> </div> <div class="ref"> <div class="ref__type">Roommate</div> <div class="ref__name">Roomies</div> <div class="ref__spec"><b>20 waves / 14 days</b> · fixed at 1 wave per send · higher count because roommate search is urgent.</div> <span style="font-family: var(--mono); font-size: 12px; color: var(--ink-soft);">Spec only</span> </div> </div>
<h2>Outside its scope</h2>
<ul> <li>A dating app or social app itself.</li> <li>A payments rail.</li> <li>A single-app backend.</li> <li>A profile data store. That lives in users’ ATProto repos.</li> </ul>
<h2>Status</h2>
<p>Glowrm is a working spec with a published API, three reference implementations, and a documentation site. It’s the trust plumbing that YGF sits on top of and that Roster and Roomies are designed against. The spec is there to make concrete the harder work of operating a real trust clearinghouse at scale: governance, appeals, due process, and regulatory standing.</p>
</div>
</article>
<footer class="foot" id="contact"> <div class="hx-icons" aria-label="Elsewhere"><a class="hx-i" href="https://bsky.app/profile/ronbronson.com" target="_blank" rel="me noopener" aria-label="Bluesky" title="Bluesky"><svg viewBox="0 0 576 512" fill="currentColor" aria-hidden="true"><path d="M407.8 294.7c-3.3-.4-6.7-.8-10-1.3 3.4 .4 6.7 .9 10 1.3zM288 227.1C261.9 176.4 190.9 81.9 124.9 35.3 61.6-9.4 37.5-1.7 21.6 5.5 3.3 13.8 0 41.9 0 58.4S9.1 194 15 213.9c19.5 65.7 89.1 87.9 153.2 80.7 3.3-.5 6.6-.9 10-1.4-3.3 .5-6.6 1-10 1.4-93.9 14-177.3 48.2-67.9 169.9 120.3 124.6 164.8-26.7 187.7-103.4 22.9 76.7 49.2 222.5 185.6 103.4 102.4-103.4 28.1-156-65.8-169.9-3.3-.4-6.7-.8-10-1.3 3.4 .4 6.7 .9 10 1.3 64.1 7.1 133.6-15.1 153.2-80.7 5.9-19.9 15-138.9 15-155.5s-3.3-44.7-21.6-52.9c-15.8-7.1-40-14.9-103.2 29.8-66.1 46.6-137.1 141.1-163.2 191.8z"></path></svg></a><a class="hx-i" href="https://mastodon.social/@ronbronson" target="_blank" rel="me noopener" aria-label="Mastodon" title="Mastodon"><svg viewBox="0 0 448 512" fill="currentColor" aria-hidden="true"><path d="M433 179.1c0-97.2-63.7-125.7-63.7-125.7-62.5-28.7-228.6-28.4-290.5 0 0 0-63.7 28.5-63.7 125.7 0 115.7-6.6 259.4 105.6 289.1 40.5 10.7 75.3 13 103.3 11.4 50.8-2.8 79.3-18.1 79.3-18.1l-1.7-36.9s-36.3 11.4-77.1 10.1c-40.4-1.4-83-4.4-89.6-54-.6-4.6-.9-9.3-.9-13.9 85.6 20.9 158.7 9.1 178.7 6.7 56.1-6.7 105-41.3 111.2-72.9 9.8-49.8 9-121.5 9-121.5zM357.9 304.3l-46.6 0 0-114.2c0-49.7-64-51.6-64 6.9l0 62.5-46.3 0 0-62.5c0-58.5-64-56.6-64-6.9l0 114.2-46.7 0c0-122.1-5.2-147.9 18.4-175 25.9-28.9 79.8-30.8 103.8 6.1l11.6 19.5 11.6-19.5c24.1-37.1 78.1-34.8 103.8-6.1 23.7 27.3 18.4 53 18.4 175l0 0z"></path></svg></a><a class="hx-i" href="https://www.linkedin.com/in/ronbronson/" target="_blank" rel="me noopener" aria-label="LinkedIn" title="LinkedIn"><svg viewBox="0 0 448 512" fill="currentColor" aria-hidden="true"><path d="M100.3 448l-92.9 0 0-299.1 92.9 0 0 299.1zM53.8 108.1C24.1 108.1 0 83.5 0 53.8 0 39.5 5.7 25.9 15.8 15.8s23.8-15.8 38-15.8 27.9 5.7 38 15.8 15.8 23.8 15.8 38c0 29.7-24.1 54.3-53.8 54.3zM447.9 448l-92.7 0 0-145.6c0-34.7-.7-79.2-48.3-79.2-48.3 0-55.7 37.7-55.7 76.7l0 148.1-92.8 0 0-299.1 89.1 0 0 40.8 1.3 0c12.4-23.5 42.7-48.3 87.9-48.3 94 0 111.3 61.9 111.3 142.3l0 164.3-.1 0z"></path></svg></a><a class="hx-i" href="https://github.com/quarterback" target="_blank" rel="me noopener" aria-label="GitHub" title="GitHub"><svg viewBox="0 0 512 512" fill="currentColor" aria-hidden="true"><path d="M216.5 362.5c-66-8-112.5-55.5-112.5-117 0-25 9-52 24-70-6.5-16.5-5.5-51.5 2-66 20-2.5 47 8 63 22.5 19-6 39-9 63.5-9s44.5 3 62.5 8.5c15.5-14 43-24.5 63-22 7 13.5 8 48.5 1.5 65.5 16 19 24.5 44.5 24.5 70.5 0 61.5-46.5 108-113.5 116.5 17 11 28.5 35 28.5 62.5l0 52C323 491.5 335.5 500 350.5 494 441 459.5 512 369 512 257 512 115.5 397 0 255.5 0S0 115.5 0 257c0 111 70.5 203 165.5 237.5 13.5 5 26.5-4 26.5-17.5l0-40c-7 3-16 5-24 5-33 0-52.5-18-66.5-51.5-5.5-13.5-11.5-21.5-23-23-6-.5-8-3-8-6 0-6 10-10.5 20-10.5 14.5 0 27 9 40 27.5 10 14.5 20.5 21 33 21s20.5-4.5 32-16c8.5-8.5 15-16 21-21z"></path></svg></a><a class="hx-i" href="https://www.instagram.com/ronbronson/" target="_blank" rel="me noopener" aria-label="Instagram" title="Instagram"><svg viewBox="0 0 448 512" fill="currentColor" aria-hidden="true"><path d="M224.3 141a115 115 0 1 0 -.6 230 115 115 0 1 0 .6-230zm-.6 40.4a74.6 74.6 0 1 1 .6 149.2 74.6 74.6 0 1 1 -.6-149.2zm93.4-45.1a26.8 26.8 0 1 1 53.6 0 26.8 26.8 0 1 1 -53.6 0zm129.7 27.2c-1.7-35.9-9.9-67.7-36.2-93.9-26.2-26.2-58-34.4-93.9-36.2-37-2.1-147.9-2.1-184.9 0-35.8 1.7-67.6 9.9-93.9 36.1s-34.4 58-36.2 93.9c-2.1 37-2.1 147.9 0 184.9 1.7 35.9 9.9 67.7 36.2 93.9s58 34.4 93.9 36.2c37 2.1 147.9 2.1 184.9 0 35.9-1.7 67.7-9.9 93.9-36.2 26.2-26.2 34.4-58 36.2-93.9 2.1-37 2.1-147.8 0-184.8zM399 388c-7.8 19.6-22.9 34.7-42.6 42.6-29.5 11.7-99.5 9-132.1 9s-102.7 2.6-132.1-9c-19.6-7.8-34.7-22.9-42.6-42.6-11.7-29.5-9-99.5-9-132.1s-2.6-102.7 9-132.1c7.8-19.6 22.9-34.7 42.6-42.6 29.5-11.7 99.5-9 132.1-9s102.7-2.6 132.1 9c19.6 7.8 34.7 22.9 42.6 42.6 11.7 29.5 9 99.5 9 132.1s2.7 102.7-9 132.1z"></path></svg></a><a class="hx-i" href="https://twitter.com/ronbronson" target="_blank" rel="me noopener" aria-label="Twitter" title="Twitter"><svg viewBox="0 0 448 512" fill="currentColor" aria-hidden="true"><path d="M357.2 48L427.8 48 273.6 224.2 455 464 313 464 201.7 318.6 74.5 464 3.8 464 168.7 275.5-5.2 48 140.4 48 240.9 180.9 357.2 48zM332.4 421.8l39.1 0-252.4-333.8-42 0 255.3 333.8z"></path></svg></a><a class="hx-i" href="https://letterboxd.com/ronbronson/" target="_blank" rel="me noopener" aria-label="Letterboxd" title="Letterboxd"><svg viewBox="0 0 640 512" fill="currentColor" aria-hidden="true"><path d="M521.3 128C586.9 128 640 181.1 640 246.6S586.9 365.2 521.3 365.2c-42.5 0-79.7-22.3-100.7-55.8 11.4-18.2 18-39.7 18-62.8s-6.6-44.6-18-62.8l.8-1.2c20.8-32.3 56.8-53.9 97.9-54.6l2 0zM320 128c42.5 0 79.7 22.3 100.7 55.8-11.4 18.2-18 39.7-18 62.8s6.6 44.6 18 62.8l-.8 1.2c-20.8 32.3-56.8 53.9-97.9 54.6l-2 0c-42.5 0-79.7-22.3-100.7-55.8 11.4-18.2 18-39.7 18-62.8s-6.6-44.6-18-62.8l.8-1.2c20.8-32.3 56.8-53.9 97.9-54.6l2 0zm-201.3 0c42.5 0 79.7 22.3 100.7 55.8-11.4 18.2-18 39.7-18 62.8s6.6 44.6 18 62.8l-.8 1.2c-20.8 32.3-56.8 53.9-97.9 54.6l-2 0C53.1 365.1 0 312.1 0 246.6S53.1 128 118.7 128z"></path></svg></a><a class="hx-i" href="https://bookhive.buzz/profile/ronbronson.com" target="_blank" rel="me noopener" aria-label="Bookhive" title="Bookhive"><svg viewBox="0 0 448 512" fill="currentColor" aria-hidden="true"><path d="M384 512L96 512c-53 0-96-43-96-96L0 96C0 43 43 0 96 0L400 0c26.5 0 48 21.5 48 48l0 288c0 20.9-13.4 38.7-32 45.3l0 66.7c17.7 0 32 14.3 32 32s-14.3 32-32 32l-32 0zM96 384c-17.7 0-32 14.3-32 32s14.3 32 32 32l256 0 0-64-256 0zm32-232c0 13.3 10.7 24 24 24l176 0c13.3 0 24-10.7 24-24s-10.7-24-24-24l-176 0c-13.3 0-24 10.7-24 24zm24 72c-13.3 0-24 10.7-24 24s10.7 24 24 24l176 0c13.3 0 24-10.7 24-24s-10.7-24-24-24l-176 0z"></path></svg></a><a class="hx-i" href="https://record.club/ron" target="_blank" rel="me noopener" aria-label="Record.club" title="Record.club"><svg viewBox="0 0 512 512" fill="currentColor" aria-hidden="true"><path d="M0 256a256 256 0 1 1 512 0 256 256 0 1 1 -512 0zm256-96a96 96 0 1 1 0 192 96 96 0 1 1 0-192zm0 240a144 144 0 1 0 0-288 144 144 0 1 0 0 288zm0-112a32 32 0 1 0 0-64 32 32 0 1 0 0 64z"></path></svg></a><a class="hx-i" href="https://listening.ronbronson.com" target="_blank" rel="me noopener" aria-label="Listening" title="Listening"><svg viewBox="0 0 448 512" fill="currentColor" aria-hidden="true"><path d="M64 224c0-88.4 71.6-160 160-160s160 71.6 160 160l0 37.5c-10-3.5-20.8-5.5-32-5.5l-16 0c-26.5 0-48 21.5-48 48l0 128c0 26.5 21.5 48 48 48l16 0c53 0 96-43 96-96l0-160C448 100.3 347.7 0 224 0S0 100.3 0 224L0 384c0 53 43 96 96 96l16 0c26.5 0 48-21.5 48-48l0-128c0-26.5-21.5-48-48-48l-16 0c-11.2 0-22 1.9-32 5.5L64 224z"></path></svg></a><a class="hx-i" href="https://www.last.fm/user/statechampion" target="_blank" rel="me noopener" aria-label="Last.fm" title="Last.fm"><svg viewBox="0 0 512 512" fill="currentColor" aria-hidden="true"><path d="M225.8 367.1l-18.8-51s-30.5 34-76.2 34c-40.5 0-69.2-35.2-69.2-91.5 0-72.1 36.4-97.9 72.1-97.9 66.5 0 74.8 53.3 100.9 134.9 18.8 56.9 54 102.6 155.4 102.6 72.7 0 122-22.3 122-80.9 0-72.9-62.7-80.6-115-92.1-25.8-5.9-33.4-16.4-33.4-34 0-19.9 15.8-31.7 41.6-31.7 28.2 0 43.4 10.6 45.7 35.8l58.6-7c-4.7-52.8-41.1-74.5-100.9-74.5-52.8 0-104.4 19.9-104.4 83.9 0 39.9 19.4 65.1 68 76.8 44.9 10.6 79.8 13.8 79.8 45.7 0 21.7-21.1 30.5-61 30.5-59.2 0-83.9-31.1-97.9-73.9-32-96.8-43.6-163-161.3-163-86.1 0-131.8 54.5-131.8 147.2 0 89.1 45.7 137.2 127.9 137.2 66.2 0 97.9-31.1 97.9-31.1z"/></svg></a><a class="hx-i" rel="me" href="mailto:ron@ronbronson.com" aria-label="Email" title="Email"><svg viewBox="0 0 512 512" fill="currentColor" aria-hidden="true"><path d="M48 64c-26.5 0-48 21.5-48 48 0 15.1 7.1 29.3 19.2 38.4l208 156c17.1 12.8 40.5 12.8 57.6 0l208-156c12.1-9.1 19.2-23.3 19.2-38.4 0-26.5-21.5-48-48-48L48 64zM0 196L0 384c0 35.3 28.7 64 64 64l384 0c35.3 0 64-28.7 64-64l0-188-198.4 148.8c-34.1 25.6-81.1 25.6-115.2 0L0 196z"></path></svg></a></div> <h2>Colophon, with digressions</h2> <p><b>Type</b> PP Neue Montreal, Hanken Grotesk, IBM Plex Mono</p> <p><b>Built with</b> HTML, CSS, JavaScript, SVG</p> <p><b>Hosting</b> GitHub, Vercel</p> <p class="digression" id="digression">Inexplicably, a Green Bay Packers shareholder.</p>
</footer>
</div> <script> /* Digressions — one aside, picked at random per load (never the same one twice in a row). Add or edit entries in DIGRESSIONS; the footer shows one at a time so the list never has to be spelled out. */ (function () { var DIGRESSIONS = [ "Inexplicably, a Green Bay Packers shareholder.", "Favorite sports teams: Toronto Blue Jays, Vimpelin Veto, New Jersey Devils, Lapuan Virkiä, <s>New York Jets</s>, Portland Timbers, New York Knicks, Portland Thorns, Brighton & Hove Albion, Sassuolo, Toluca, Toronto Tempo, Montreal Expos (RIP)", "<em>Have you seen my fragrance collection?</em> <a href='https://www.oksmelly.xyz/' target='_blank' rel='noopener'>it’s here</a>.", "I’m a longtime tea sommelier. I once curated the tea menu at <a href='https://hopscotchcoffee.com/' target='_blank' rel='noopener'>Hopscotch Coffee</a> in Bloomington. Ask me for loose-leaf recs!", "Favorite wine regions: Slovenia, Georgia or anything that aged in amphorae or an old boot. I’m not picky.", "I’ve coached high school tennis for ten years across 3 states. My career varsity record apparently is 91-33-4. 1 team state championship, 4 District/Regional titles, 5 Conference titles. 4 individual state champions. So far…", "Yes, I have a <a href='https://www.discogs.com/user/quarterback/collection?header=1' target='_blank' rel='noopener'>Discogs</a> 🙄", "I actually grew up watching golf, because my grandfather played. I still like a Par 3 because of him.", "Last time I went fishing? 1994.", "Unsurprisingly, I was once a bar trivia host in Bloomington. One step closer to my true calling: game show host." ]; var el = document.getElementById("digression"); if (!el) return; var last = -1; try { last = parseInt(sessionStorage.getItem("rb-digression"), 10); } catch (e) {} var i = Math.floor(Math.random() * DIGRESSIONS.length); while (DIGRESSIONS.length > 1 && i === last) i = Math.floor(Math.random() * DIGRESSIONS.length); try { sessionStorage.setItem("rb-digression", i); } catch (e) {} el.innerHTML = DIGRESSIONS[i]; })(); </script></body></html>