<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/pretty-feed-v3.xsl" type="text/xsl"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>daverupert.com</title>
    <description>The personal blog of Dave Rupert, web developer and podcaster from Austin, TX.</description>
    <link>https://daverupert.com</link>
    <atom:link href="https://daverupert.com/atom.xml" rel="self" type="application/rss+xml" />
    
      <item>
        <title>Smaller and dumber</title>
        <description>&lt;p&gt;If I can make it smaller, I should.&lt;/p&gt;
&lt;p&gt;If I can make it dumber, I should.&lt;/p&gt;
&lt;p&gt;Smaller, dumber things have more applications, go more places, and require less maintenance.&lt;/p&gt;
</description>
        <pubDate>Mon, 23 Feb 2026 05:33:00 +0000</pubDate>
        <link>https://daverupert.com/2026/02/smaller-and-dumber/</link>
        <guid isPermaLink="true">https://daverupert.com/2026/02/smaller-and-dumber/</guid>
      </item>
    
      <item>
        <title>Priority of idle hands</title>
        <description>&lt;p&gt;I had a small, intrusive realization the other day that computers and the internet are probably bad for me. I mean that beyond the general advice to touch grass. From an ADHD and generalized anxiety perspective, computers and the internet have become an endless supply of poison pills for my brain; feeds full of constant dopamine hits with doom at every turn.&lt;/p&gt;
&lt;p&gt;This is hard to accept because a lot of my work, hobbies, education, entertainment, news, communities, and curiosities are all on the internet. I love the internet, it’s a big part of who I am today, but I understand how its incentive structures harm me. I’m not planning to unplug and go off-grid yet, but it did inspire me to come up with a “&lt;a href=&quot;https://www.w3.org/TR/html-design-principles/#priority-of-constituencies&quot;&gt;priority of constituencies&lt;/a&gt;” for my idle hands and downtime:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Instruments over pads of paper over laptop over tablet over phone.&lt;/em&gt;&lt;/p&gt;
</description>
        <pubDate>Mon, 23 Feb 2026 03:13:00 +0000</pubDate>
        <link>https://daverupert.com/2026/02/computers-were-a-mistake-for-me/</link>
        <guid isPermaLink="true">https://daverupert.com/2026/02/computers-were-a-mistake-for-me/</guid>
      </item>
    
      <item>
        <title>Magic Words</title>
        <description>&lt;p&gt;Skills are the newest hype commodity in the world of agentic AI. Skills are text files that optionally get stapled onto the context window by the agent. You can have skills like “frontend design” or “design tokens” and if the LLM “thinks” it needs more context about that topic, it can import the contents of those files into the context to help generate a response.&lt;/p&gt;
&lt;p&gt;Generally speaking, skills do an okay job at providing on-demand context. Assuming the AI model is always 12-to-18 months behind in its training data, a skill could potentially backfill any recent framework updates. A skill could potentially undo some training data biases. A skill could potentially apply some of your sensibilities to the output. I’ve seen some impressive results with design guidance skills… but I’ve also seen tons of mediocre results from the same skills. That’s why I deliberately use the word “potentially”. When skills can be optionally included, it’s hard to understand the &lt;em&gt;when&lt;/em&gt; and &lt;em&gt;why&lt;/em&gt; behind how they get applied.&lt;/p&gt;
&lt;p&gt;In that way, skills remind me a bit of magic numbers.&lt;/p&gt;
&lt;p&gt;In programming “&lt;a href=&quot;https://en.wikipedia.org/wiki/Magic_number_(programming)&quot;&gt;magic numbers&lt;/a&gt;” are a pattern you typically try to avoid. They’re a code smell that you haven’t actually solved the problem, but found a workaround that only works in a particular context. They’re a flashing light that you have brittle logic somewhere in your system. “We don’t know why, but setting the value to &lt;code&gt;42&lt;/code&gt; appears to have fixed the issue” is a phrase that should send shivers down the spine.&lt;/p&gt;
&lt;p&gt;And so now we have these “magic words” in our codebases. Spells, essentially. Spells that work sometimes. Spells that we cast with no practical way to measure their effectiveness. They are prayers as much as they are instructions.&lt;/p&gt;
&lt;p&gt;Were we to sit next to each other and cast the same spell from the same book with the same wand; one of us could have a graceful floating feather and the other could have &lt;em&gt;avada kedavra&lt;/em&gt;’d their guts out onto the floor. That unstable magic is &lt;em&gt;by design&lt;/em&gt;. That element of randomness –to which the models depend– still gives me apprehension.&lt;/p&gt;
&lt;p&gt;There’s an opaqueness to it all. I understand how listing skills in an &lt;code&gt;AGENTS.md&lt;/code&gt; gives the agent context on where to find more context. But how do you know if those words are the right words? If I cut the amount of words (read: “tokens”) in a skill in half, does it still work? If I double the amount of words, does it work better? Those questions matter when too little context is not enough context and too much context causes context rot. It also matters when you’re charged per-token and more tokens is more time on the GPU. How do you determine the “Minimum Viable Context” needed to get quality out of the machines?&lt;/p&gt;
&lt;p&gt;That sort of quality variance is uncomfortable for me from a tooling perspective. Tooling should be highly consistent and this has a “works on my machine” vibe to it. I suppose all my discomfort goes away if I quit caring about the outputs. If I embrace the cognitive dissonance and switch to a “ZOMG the future is amazeballs” hype mode, my job becomes a lot easier. But my brain has been unsuccessful in doing that thus far. I like magic and mystery, but hope- or luck-based development has its challenges for me.&lt;/p&gt;
&lt;p&gt;Looking ahead, I expect these types of errant conjurations will come under more scrutiny when the free money subsidies run out and consumers inherit the full cost of the models’ mistakes. Supply chain constraints around memory and GPUs are already making compute a scarce resource, but our Gas Towns plunder onward. When the cost of wrong answers goes up and more and more people spend all their monthly credits on hallucinations, that will be a lot of dissatisfied users.&lt;/p&gt;
&lt;p&gt;Anyways, all this changes so much. Today it’s skills, before that MCP, before that PRDs, before that prompt engineering… what is it going to be next quarter? And aren’t those all flavors of the same managing context puzzle? Churn, churn, churn, I suppose.&lt;/p&gt;
&lt;p&gt;File under: &lt;code&gt;non-determinism&lt;/code&gt;&lt;/p&gt;
</description>
        <pubDate>Mon, 09 Feb 2026 16:03:00 +0000</pubDate>
        <link>https://daverupert.com/2026/02/magic-words/</link>
        <guid isPermaLink="true">https://daverupert.com/2026/02/magic-words/</guid>
      </item>
    
      <item>
        <title>Write about the future you want</title>
        <description>&lt;p&gt;There’s a lot that’s not going well; politics, tech bubbles, the economy, and so on. I spend most of my day reading angry tweets and blog posts. There’s a lot to be upset about, so that’s understandable. But in the interest of fostering better discourse, I’d like to offer a challenge that I think the world desperately needs right now: It’s cheap and easy to complain and say “[Thing] is bad”, but it’s also free to share what you think would be better.&lt;/p&gt;
&lt;p&gt;If complaining worked, we would have won the culture war already. We’d have a reformed Elon and the White House wouldn’t be committing crimes against humanity. But that’s not the world we live in. The one we live in is much worse. If you hate the here and now, write about what would be a better future. Write about &lt;em&gt;what’s good&lt;/em&gt; and why &lt;em&gt;more of that good&lt;/em&gt; would &lt;em&gt;be good&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;If you believe the current trend in tech is exploitative, write about tech that isn’t. What impresses you? What compromises did you make? Are you happy? Does giving money to a small bootstrapped company feel ten thousand times better than a large venture-backed company like I imagine? Can you list some of those out for me? Show me where I can throw my dollars.&lt;/p&gt;
&lt;p&gt;If you detest content theft at a massive scale, describe a world where copyright matters. Tell me how you’re only going to watch TikToks with royalty free music from now on and not use an ad-blocker. Tell me how you’re going to delete that hard-drive of pirated content. No? Then invent a better copyright system! Talk about the commons and how we should tax people who abuse it by taking more than they give. What does that system look like?&lt;/p&gt;
&lt;p&gt;If you detest the ecological impact of AI data centers, propose an alternative piece of technology that drives shareholder value. Or advocate for a broader, more equitable definition of &lt;a href=&quot;https://www.ibm.com/think/topics/responsible-ai&quot;&gt;Responsible AI&lt;/a&gt;. Don’t let the Effective Altruists define the terms. &lt;a href=&quot;https://dbushell.com/ai/&quot;&gt;Itemize the problems&lt;/a&gt; and then dream up a version that doesn’t have those. List demands. Find levers. Or make the case for how small, local, private, and less energy-intensive models are probably “good enough” for most use cases and we should stop burning barrels of crude and use those instead. If we must throw it away, point people to organizations and political groups working towards that end.&lt;/p&gt;
&lt;p&gt;If you believe billionaires are the problem, talk about a world without them. Share how we redistribute a billionaire tax equitably and talk about the impact it has on society. Make a spreadsheet or a chart. Get into numbers. Talk about degrowth. I know that “Line Goes Up” has problems and won’t work forever, but how are my family and I more okay if we undo centuries of continued economic growth and technical acceleration.&lt;/p&gt;
&lt;p&gt;I think history is wrought with examples of this working; Dr. King’s “I have a Dream” speech, the Federalist Papers, David Hasselhoff singing at the Berlin Wall during the height of the Cold War… the list goes on. Few will rise to the level of Ambassador Hasselhoff, but I don’t have to look far to find people around me who have inspired me by writing about the future they want.&lt;/p&gt;
&lt;p&gt;After repeated mass layoffs, &lt;a href=&quot;https://ethanmarcotte.com/&quot;&gt;Ethan Marcotte&lt;/a&gt; identified a problem with the wealth and labor dynamics in the tech industry. While Ethan could have been perfectly happy bitching about it on Twitter, he didn’t do that. Instead, he put hands to keyboard and made a talk, which turned into &lt;a href=&quot;https://ethanmarcotte.com/books/you-deserve-a-tech-union/&quot;&gt;a book&lt;/a&gt;, about what he feels is the time-tested solution to our predicament: Unions. Truthfully, I’m not particularly predispositioned to be pro-union (Texan, etc), but Ethan and I agree on the problem. Seeing Ethan &lt;a href=&quot;https://journal.stuffwithstuff.com/2026/01/24/the-value-of-things/&quot;&gt;spend time&lt;/a&gt; to communicate the problem and explore the solution changed my opinion on unions. And while I certainly still have nuanced questions, Ethan convinced me that collective action is the best leverage workers have against abuses of labor. That wouldn’t have happened without Ethan’s dedication to highlighting the problem &lt;em&gt;and the solution&lt;/em&gt; over many years.&lt;/p&gt;
&lt;p&gt;Often people need you to &lt;em&gt;show, not tell&lt;/em&gt; the alternative. You need to paint a picture. Not a full complete picture, but one where a person can paint themselves in it. When people want change and bad change is happening all around them, that’s a hopeless place. Build a raft of opportunity that people can latch onto in the rough open waters, instead of hitting them with spears.&lt;/p&gt;
</description>
        <pubDate>Wed, 04 Feb 2026 15:45:00 +0000</pubDate>
        <link>https://daverupert.com/2026/02/futurescapes/</link>
        <guid isPermaLink="true">https://daverupert.com/2026/02/futurescapes/</guid>
      </item>
    
      <item>
        <title>I&apos;m swearing off APIs entirely</title>
        <description>&lt;p&gt;I got a lot of ideas for side projects rattling around in the old tin can. As part of my “No new projects” initiative, I’m trying to jump on building prototypes so I can decide if I want to explore ideas more or call it quits. A handful of my ideas are riffs or twists on existing app categories:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A tennis ranking app… but modern and performant&lt;/li&gt;
&lt;li&gt;A nearby historical marker app… but with CarPlay support&lt;/li&gt;
&lt;li&gt;A nearby real estate listing app… but with CarPlay support&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All three of those have ended unceremoniously at the same dead end: no API access. USTA denied my application for tennis rankings. The aptly named Historical Marker Database site doesn’t have a public API. And you have to be an MLS® Realtor® or Broker to get access to the MLS® listings. Womp womp.&lt;/p&gt;
&lt;p&gt;Scraping the data is always an option… but I don’t like the ethics of that and worry about the brittleness of that dependency.&lt;/p&gt;
&lt;p&gt;Ugh. I wish I could build these little apps so that tens of people could enjoy them. I’d even be willing to pay a small API access fee ($10/mo?) and run these at a loss but whatever happened to free APIs. When I &lt;a href=&quot;https://github.com/public-api-lists/public-api-lists&quot;&gt;survey the land of public APIs&lt;/a&gt; it feels like we’ve lost a lot since the Web 2.0 days where API access was almost a God-given right.&lt;/p&gt;
&lt;p&gt;To prevent this time loop of disappointment from happening again, I’m swearing off APIs entirely. That’s a hard stance, but I need a backstop at the idea phase to prevent me from wasting limited life force. If I don’t have the data, or can’t generate the data, or it’s not an open protocol… it’s not worth building or even thinking about.&lt;/p&gt;
&lt;p&gt;OAuth apps are a good option and generally the best way to exfiltrate data because it’s tied to a user’s account…. but you still might run into call limits, incomplete endpoints, user-scope limitations, and so on. History also shows us what the future holds. There’s a Tweetbot-style risk when building on a someone else’s platform. Even if your app drives activity to the parent application, your access might get cut because it competes or doesn’t drive stakeholder value. And if the idea isn’t big enough, being “a feature, not a product” is also a bad position to be in, lest you get Sherlock’d.&lt;/p&gt;
&lt;p&gt;Where’s that leave me and my pile of side project ideas? Thankfully… in a good place. I can close out these project tabs and free up some much needed Brain RAM. It sounds strange but “No more APIs” makes “Making video games” jump up in the viability rankings for side projects too, because games have closed ecosystems. Or I could spend more time writing shitty sci-fi. Write a serial. Print some zines. Who knows.&lt;/p&gt;
&lt;p&gt;If the goal of “No new projects” is to finish more projects than I start, then I have to accept that part of figuring out which ideas to explore means “&lt;a href=&quot;https://www.youtube.com/watch?v=RfiQYRn7fBg&quot;&gt;Nope&lt;/a&gt;” is a potential answer. It’s also not a total loss, I’m learning along the way. For example, &lt;a href=&quot;https://developer.apple.com/download/files/CarPlay-Developer-Guide.pdf&quot;&gt;CarPlay only lets you choose from eight pre-approved templates&lt;/a&gt;. There’s also pre-defined app categories and diverting in the slightest would almost guarantee App Store rejection. That sucks the fun out it… but ayyyy, I’ll probably try again. But now I know the limitation for future projects and its in the limitations where play begins.&lt;/p&gt;
</description>
        <pubDate>Mon, 26 Jan 2026 06:27:00 +0000</pubDate>
        <link>https://daverupert.com/2026/01/hitting-my-api-limits/</link>
        <guid isPermaLink="true">https://daverupert.com/2026/01/hitting-my-api-limits/</guid>
      </item>
    
      <item>
        <title>Waiting for the power to go out</title>
        <description>&lt;p&gt;&lt;tt&gt;It’s a secret to everyone! This post is for RSS subscribers only.
&lt;a href=&quot;https://daverupert.com/rss-club/&quot;&gt;Read more about RSS Club&lt;/a&gt;.
&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;It’s expected to freeze this evening in Austin and we may even see snow, which is exciting and novel for us Texans. But as we’ve learned in 2021 and 2023, cold snaps can lead to disaster. In those years the ice dealt untold damages as foot-thick tree limbs fell from the canopy like enormous glass Cadillacs. The crackle, pop, followed by crystalline shatter in the cold dead air is a sound I won’t forget. With the falling trees came down power lines and the lights went out.&lt;/p&gt;
&lt;p&gt;It got worse. &lt;a href=&quot;https://www.kut.org/the-disconnect&quot;&gt;The disconnected Texas power grid failed&lt;/a&gt;. As homes and empty office buildings required more heating in the “extreme” cold, the rolling blackouts began to shed load. Except… they didn’t roll. Homes next to facilities (hospitals, fire stations, and water treatment plants) deemed critical were fine, but the rest of us were off-grid in the cold for nearly a week. The energy companies could have met capacity, but quit making energy because they would have had to sell it at a loss. Greed until the state promised them a windfall.&lt;/p&gt;
&lt;p&gt;The infrastructure failed. Pipes burst, homes flooded, and trauma increased. While our senator and his banker wife fled to Mexico to stay in a Ritz Carlton, Texans burned their IKEA furniture and cedar fences to stay warm.&lt;/p&gt;
&lt;p&gt;Building on past lessons, we’ve made all the preparations for today; external faucets capped, plants covered, and I built a cabinet out of foam board insulation for our external hot water heater. And now we wait… we wait to see if the Libertarian Capitalist systems my state has put into place will hold up. Waiting to see if the power goes out. Waiting for the impending disaster.&lt;/p&gt;
&lt;p&gt;If you’ve ever had a child, you might know this feeling. You’ve taken the classes, assembled the crib, child-proofed the outlets, and then you wait… you wait for your life to change. While the miracle of childbirth is a beautiful event, any mother can tell you it’s not without some drawbacks. From prolonged labor, painful contractions, episiotomies, and beyond… every birth is a dice-roll of potentially life-threatening complications. A friend of mine who had three kids described it well; “Having a baby is like knowing you’ll be in a car accident.”&lt;/p&gt;
&lt;p&gt;That feeling of pregnant, expectant waiting dominates a lot of my life right now as I wait for all the larger meta narratives in our country to unravel. I’m waiting for a mid-term election, one where I feel the fabric of democracy hangs by a thread. I’m waiting for an opposition party that has a fucking plan, but I don’t see one yet. I’m waiting for a particular person to leave office… or (preferred) die of natural causes. I’m waiting for the full release of the Epstein files, so the victims of billionaire pedophilia and human trafficking can have justice. I’m waiting for the government to stop its reign of cruelty on its own people, but masked fascists killed another innocent person in broad daylight today. I’m waiting for the economy to work for most Americans, not only the wealthy. I’m waiting for either the tech bubble to pop or for the robots to take my job… either way I’d like this story line to wrap up soon but I must ask, is there a third option? I’m waiting for the next big thing and praying it’s something that makes the world more loving and kind, but a new global religion would be a lot to deal with right now.&lt;/p&gt;
</description>
        <pubDate>Sat, 24 Jan 2026 21:44:00 +0000</pubDate>
        <link>https://daverupert.com/2026/01/waiting-for-the-power-to-go-out/</link>
        <guid isPermaLink="true">https://daverupert.com/2026/01/waiting-for-the-power-to-go-out/</guid>
      </item>
    
      <item>
        <title>The best version of my site so far...</title>
        <description>&lt;p&gt;You might have noticed that I did a big design refresh on my entire site… unless you’re on RSS I guess. I’ll talk about aspects in detail, but at a high level there’s been three big changes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A monospace font&lt;/li&gt;
&lt;li&gt;Named CSS grid lines&lt;/li&gt;
&lt;li&gt;Juicier multi-page view transitions&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;But my most favorite part is that today  (when you set &lt;code&gt;html { --hue-rotate: 15 }&lt;/code&gt;), my light theme looks like a stick of butter. And that brings me joy.&lt;/p&gt;
&lt;h2&gt;What didn’t change&lt;/h2&gt;
&lt;p&gt;Before I talk about what changed, here’s a quick list of the parts of my site that didn’t change:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Same big “Dave” SVG on the homepage&lt;/li&gt;
&lt;li&gt;Same information architecture, no radical content changes.&lt;/li&gt;
&lt;li&gt;No new assets, same visuals.&lt;/li&gt;
&lt;li&gt;Same &lt;a href=&quot;https://daverupert.com/2025/01/color-hue-rotating-gaslight/&quot;&gt;hue-rotating background&lt;/a&gt;, although I did simplify the formula.&lt;/li&gt;
&lt;li&gt;Same &lt;a href=&quot;https://daverupert.com/2025/06/fittext-too-attr-boogaloo/&quot;&gt;inverse text-sizing&lt;/a&gt; for H1s&lt;/li&gt;
&lt;li&gt;Same &lt;a href=&quot;https://daverupert.com/2021/01/art-direction-for-static-sites/&quot;&gt;support for art-directed posts&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Why change the parts you’re happy with, eh? Knowing what you want to change versus what you don’t want to change makes the whole process go faster.&lt;/p&gt;
&lt;h2&gt;All-in on a monospace font&lt;/h2&gt;
&lt;p&gt;My type system always falls apart. I start with a good setup and I’m guaranteed to ruin it over time. Whenever I read a site with a nice typeface and reasonable CPL, I started to feel like my &lt;code&gt;system-ui&lt;/code&gt; based body text styles were letting me down. It didn’t feel cozy.&lt;/p&gt;
&lt;p&gt;Then I saw &lt;a href=&quot;https://robinrendle.com/&quot;&gt;Robin Rendle&lt;/a&gt;’s latest redesign (which is wonderful, btw) I wondered… Could I be a &lt;code&gt;monospace&lt;/code&gt; font guy? Is that me? Do I identify as that? Is it too emo? Does it come off as a bad developer pun like &lt;code&gt;bleep blorp I&apos;m a programmer and using a computer bleep blorp&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;All good questions to ask myself and exposes some insecurity I have, but I couldn’t shake the idea so I went for it.&lt;/p&gt;
&lt;p&gt;The entire site is now set in &lt;code&gt;Cascadia Mono&lt;/code&gt; which is a variant of Microsoft’s &lt;a href=&quot;https://github.com/microsoft/cascadia-mono&quot;&gt;Cascadia Code&lt;/a&gt;. That decision is unintentionally on-brand for my current stage of life. Initially I wanted to use &lt;a href=&quot;https://levien.com/type/myfonts/inconsolata.html&quot;&gt;Inconsolata&lt;/a&gt; by Raph Levien, but it didn’t have a “numero” (№) symbol – which is a common missing glyph in a lot of indie fonts – and is an unfortunate piece of critical typographical infrastructure with my &lt;a href=&quot;https://daverupert.com/tag/vibecheck&quot;&gt;vibechecks&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In general I love the change. It feels very “me” right now. I worry about the readability of monospace fonts some, but I don’t think I was winning the Legibility Wars before.&lt;/p&gt;
&lt;h2&gt;Naming my grid lines&lt;/h2&gt;
&lt;p&gt;Improving the grid on my site is something I’ve wanted to do for nearly two years. The max-width container I had was fine before, but I relied a lot on &lt;a href=&quot;https://daverupert.com/2017/03/full-bleed-with-not/&quot;&gt;margin overrides&lt;/a&gt; to change a container that &lt;a href=&quot;https://daverupert.com/2017/03/thoughts-on-negative-margins/&quot;&gt;felt like a hack&lt;/a&gt; that in my experience don’t scale.&lt;/p&gt;
&lt;p&gt;Now I have something better with some sweet tech from &lt;a href=&quot;https://smolcss.dev/#smol-breakout-grid&quot;&gt;Stephanie Eckles&lt;/a&gt; that I saw on &lt;a href=&quot;https://www.youtube.com/watch?v=c13gpBrnGEw&quot;&gt;Kevin Powell’s YouTube&lt;/a&gt; called “Named Grid Lines”. A not-so-well-known feature of grid is you can name the gutters in your grid template. The result is a grid that looks like this:&lt;/p&gt;
&lt;grid-container-demo&gt;
  &lt;div class=&quot;full&quot;&gt;Full&lt;/div&gt;
  &lt;div class=&quot;margin&quot;&gt;Margin&lt;/div&gt;
  &lt;div class=&quot;wide&quot;&gt;Wide&lt;/div&gt;
  &lt;div class=&quot;outdent&quot;&gt;Outdent&lt;/div&gt;
  &lt;div&gt;Content (Default)&lt;/div&gt;
&lt;/grid-container-demo&gt;
&lt;p&gt;See how all the grids collapse into one line that’s offset from the edge? That’s what I want. And then to use it, you specify the &lt;code&gt;*-start&lt;/code&gt; and &lt;code&gt;*-end&lt;/code&gt; line you tweak your container with a modifier class and make all the children start at a different grid line.&lt;/p&gt;
&lt;div class=&quot;language-css highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code data-lang=&quot;css&quot;&gt;&lt;span class=&quot;nc&quot;&gt;.foo.container&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;nl&quot;&gt;grid-column&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wide-start&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wide-end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; 
  &lt;span class=&quot;c&quot;&gt;/* or grid-column: wide */&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This gives me a lot of scalable control for my layout at the template level. For example, the layout of my homepage looks like this:&lt;/p&gt;
&lt;grid-container-demo&gt;
  &lt;div class=&quot;outdent&quot;&gt;Header&lt;/div&gt;
  &lt;div class=&quot;outdent&quot;&gt;Logo&lt;/div&gt;
  &lt;div&gt;Latest Posts&lt;/div&gt;
  &lt;div&gt;Projects&lt;/div&gt;
  &lt;div class=&quot;outdent&quot;&gt;Footer&lt;/div&gt;
&lt;/grid-container-demo&gt;
&lt;p&gt;But when you click through to a single post, the template shifts to this:&lt;/p&gt;
&lt;grid-container-demo&gt;
  &lt;div class=&quot;outdent&quot;&gt;Header&lt;/div&gt;
  &lt;div class=&quot;outdent-end&quot;&gt;Title Goes Here&lt;/div&gt;
  &lt;div&gt;Content&lt;/div&gt;
  &lt;div class=&quot;outdent-end&quot;&gt;Media&lt;/div&gt;
  &lt;div&gt;Content&lt;/div&gt;
    &lt;div&gt;Content&lt;/div&gt;
  &lt;div class=&quot;outdent-end&quot;&gt;Media&lt;/div&gt;
    &lt;div&gt;Content&lt;/div&gt;
    &lt;div&gt;Content&lt;/div&gt;
  &lt;div class=&quot;outdent&quot;&gt;Footer&lt;/div&gt;
&lt;/grid-container-demo&gt;
&lt;p&gt;I don’t have this setup, but I could write out a system of utility classes to make all this super flexible.&lt;/p&gt;
&lt;grid-container-demo&gt;
  &lt;div class=&quot;full-start&quot;&gt;.full-start&lt;/div&gt;
  &lt;div class=&quot;margin-start&quot;&gt;.margin-start&lt;/div&gt;
  &lt;div class=&quot;wide-start&quot;&gt;.wide-start&lt;/div&gt;
  &lt;div class=&quot;outdent-start&quot;&gt;.outdent-start&lt;/div&gt;
  &lt;div&gt;Default Content&lt;/div&gt;
  &lt;div class=&quot;outdent-end&quot;&gt;.outdent-end&lt;/div&gt;
  &lt;div class=&quot;wide-end&quot;&gt;.wide-end&lt;/div&gt;
  &lt;div class=&quot;margin-end&quot;&gt;.margin-end&lt;/div&gt;
  &lt;div class=&quot;full-end&quot;&gt;.full-end&lt;/div&gt;
&lt;/grid-container-demo&gt;
&lt;p&gt;That’s a lot of different layouts to craft. I look forward to more sustainable art direction for years to come. No more hacky negative margins or fixed positioned items… right?&lt;/p&gt;
&lt;h2&gt;More Multipage View Transitions&lt;/h2&gt;
&lt;p&gt;I’ve had &lt;a href=&quot;https://daverupert.com/2023/05/getting-started-view-transitions/&quot;&gt;multi-page view transitions on my site&lt;/a&gt; for years now. The original was a title transition from the index template to the post template where the post title would do a subtle swoop up and morph from an &lt;code&gt;H3&lt;/code&gt; to display-sized &lt;code&gt;H1&lt;/code&gt;. This was great until I changed the font for my &lt;code&gt;H1&lt;/code&gt; (see above) and I obliterated the slight of hand magic I had before. Oops.&lt;/p&gt;
&lt;p&gt;Now the flagship animation on my site is not typography dependent. If you navigate through my site, you’ll see that the “Dave” SVG on the homepage transitions into the main navigation on subpages. As a bonus, I get a little bit of much-needed branding on subpages. I didn’t do anything special other than naming the view transition and beefing up the stroke when the logo is in its smaller form.&lt;/p&gt;
&lt;p&gt;The main nav is out-dented a bit by default, but using my new named columns I made the navigation go wider to match wide pages like my Bookshelf. Flexbox’s &lt;code&gt;justify-content: space-between&lt;/code&gt; and view-transitions is doing all the heavy lifting on that animation there but I’m pleased with the effect and it feels natural (aka not synthetic and cheap).&lt;/p&gt;
&lt;p&gt;I’m not a motion expert like &lt;a href=&quot;https://cydstumpel.nl/&quot;&gt;Cyd Stumpel&lt;/a&gt;, but it feels good to have big, bold, un-ignorable view transitions on my site.&lt;/p&gt;
&lt;h2&gt;Slimmed down CSS&lt;/h2&gt;
&lt;p&gt;A redesign is always a great opportunity to clean house. I did the thing where I deleted my entire CSS and started from a naked page. Bit-by-bit I pulled back in the pieces I still needed.&lt;/p&gt;
&lt;p&gt;I have about 40% less CSS which manifests in ~150 less lines of code to maintain and up to &lt;code&gt;~0.8 KB&lt;/code&gt; when compressed over the wire.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;LoC&lt;/th&gt;
&lt;th&gt;Raw&lt;/th&gt;
&lt;th&gt;Min+Gzip&lt;/th&gt;
&lt;th&gt;Min+Brotli&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Before&lt;/td&gt;
&lt;td&gt;557&lt;/td&gt;
&lt;td&gt;10.3 KB&lt;/td&gt;
&lt;td&gt;2.76 KB&lt;/td&gt;
&lt;td&gt;2.43 KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;After&lt;/td&gt;
&lt;td&gt;391&lt;/td&gt;
&lt;td&gt;5.36 KB&lt;/td&gt;
&lt;td&gt;1.97 KB&lt;/td&gt;
&lt;td&gt;1.76 KB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Now &lt;code&gt;0.8 KB&lt;/code&gt; isn’t much but because I inline my critical CSS the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; on every page, this number matters. My entire homepage document is &lt;code&gt;~5.5 KB&lt;/code&gt; (Brotli), so that’s a 10%~20% performance improvement from cleaning up my CSS. How did I get these gains, you ask? Well…&lt;/p&gt;
&lt;p&gt;One reason my CSS smaller is because I’m using modern CSS (nesting, &lt;code&gt;:has()&lt;/code&gt;, &lt;code&gt;:is()&lt;/code&gt;, &lt;code&gt;:where()&lt;/code&gt;, &lt;code&gt;:not()&lt;/code&gt;, etc). Those features seem like minor syntactic sugar but you also get more efficient selectors. For example my out-denting that I do in posts would previous be something like:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;.post iframe, 
.post video, 
.post img,
.post table { }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;In modern CSS that super-conjoined selector becomes something more expressive and elegant:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;.post :is(iframe, video, img, table) {}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Those small improvements add up, but another reason the CSS is smaller is because its doing a lot less. Other than my inverse-sized H1s in posts, I’m not managing type styles at all beyond setting the body font-size. I think this is what Andy Bell calls “&lt;a href=&quot;https://bell.bz/be-the-browsers-mentor-not-its-micromanager/&quot;&gt;Be the Browser’s Mentor, Not Its Micromanager&lt;/a&gt;”. My strategy here is: Don’t futz with it until you can think of something way better than what the browser already does. That seems very &lt;a href=&quot;https://alistapart.com/article/dao/&quot;&gt;Dao&lt;/a&gt; or &lt;a href=&quot;https://frankchimero.com/blog/2015/the-webs-grain/&quot;&gt;Web’s Grain’y&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Onward to more art direction!&lt;/h2&gt;
&lt;p&gt;This redesign opens up a bright future for my site. I’ve already started on some of this work, but I’ll share that in a future post. I mentioned above but the named grid lines alone give me a lot of easy-to-use levers for expression. I touched up some &lt;a href=&quot;https://daverupert.com/2020/04/oh-the-paywalls-you-ll-meet/&quot;&gt;old art-directed posts&lt;/a&gt; and they are benefitting from the changes already.&lt;/p&gt;
&lt;p&gt;“Make it easy to play” seems like a good ethos for a personal site and I feel like I have that in the current manifestation.&lt;/p&gt;
</description>
        <pubDate>Sun, 18 Jan 2026 14:29:00 +0000</pubDate>
        <link>https://daverupert.com/2026/01/my-2026-redesign/</link>
        <guid isPermaLink="true">https://daverupert.com/2026/01/my-2026-redesign/</guid>
      </item>
    
      <item>
        <title>Focus rings with nested contrast-color()?</title>
        <description>&lt;p&gt;As I was playing around with &lt;code&gt;contrast-color()&lt;/code&gt;, I got a wild idea that you could use &lt;code&gt;contrast-color()&lt;/code&gt; to invert its return value by nesting it: &lt;code&gt;contrast-color(contrast-color(var(--some-color))&lt;/code&gt;. When would this be useful? Uh… Good question. I couldn’t come up with an example right away but after a bit I found one sitting right under my nose….&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.daverupert.com/posts/2026/focus-rings.jpg&quot; alt=&quot;four buttons in one line. a secondary button, an accented primary button with a focus state, a subtle button and a transparent button&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Our focus-rings in &lt;a href=&quot;https://storybooks.fluentui.dev/web-components/&quot;&gt;Fluent&lt;/a&gt; use a 1px inset white highlight and a 2px offset black focus-ring. It’s a smidge chonkier than the Chromium default. The reason we do this is to guarantee contrast against the focused-element, in the above example, a blue button. Without the addition of the white stroke, the black outline wouldn’t “pop” with enough contrast to the blue background.&lt;/p&gt;
&lt;p&gt;To make this work, we have a &lt;code&gt;--focus-inner-ring&lt;/code&gt; token and a &lt;code&gt;--focus-outer-ring&lt;/code&gt; token themed for both light and dark modes.&lt;/p&gt;
&lt;div class=&quot;language-css highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code data-lang=&quot;css&quot;&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;:focus-visible&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;box-shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1px&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--focus-inner-ring&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;outline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2px&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;solid&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--focus-outer-ring&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;outline-offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;How would this change with nested &lt;code&gt;contrast-color()&lt;/code&gt;?&lt;/p&gt;
&lt;div class=&quot;language-css highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code data-lang=&quot;css&quot;&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;:focus-visible&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;outline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2px&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;solid&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contrast-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--page-bg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;outline-offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;box-shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1px&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contrast-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contrast-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--page-bg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;All you would need is one token you probably already have (&lt;code&gt;--page-bg&lt;/code&gt;) vs two tokens. Neat.&lt;/p&gt;
&lt;p&gt;One consideration… your focus-ring isn’t always on a &lt;code&gt;--page-bg&lt;/code&gt;. Sometimes it shows up on a &lt;code&gt;--card-bg&lt;/code&gt; and this little trick might fall apart. As always, your mileage may vary.&lt;/p&gt;
&lt;p&gt;Aside: This got me thinking it’d be nice to have a &lt;code&gt;currentBackgroundColor&lt;/code&gt; like we have &lt;code&gt;currentColor&lt;/code&gt; in CSS today.  I’m not sure how much career I’ve got left to wait for that, but who knows.&lt;/p&gt;
&lt;h2&gt;On second thought…&lt;/h2&gt;
&lt;p&gt;Mulling this over a bit more… you might be better off using &lt;code&gt;color-scheme&lt;/code&gt; and &lt;code&gt;light-dark()&lt;/code&gt; for this instead.&lt;/p&gt;
&lt;div class=&quot;language-css highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code data-lang=&quot;css&quot;&gt; &lt;span class=&quot;nd&quot;&gt;:root&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	 &lt;span class=&quot;py&quot;&gt;color-scheme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;light&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
 
 &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;:focus-visible&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;nl&quot;&gt;box-shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1px&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;light-dark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;white&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;black&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
   &lt;span class=&quot;nl&quot;&gt;outline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2px&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;solid&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;light-dark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;black&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;white&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
   &lt;span class=&quot;nl&quot;&gt;outline-offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Yeah… I’d probably do that. You dodge the spotty &lt;code&gt;contrast-color()&lt;/code&gt; support and have a singular function instead of a nested situation. It keeps it simple and readable.&lt;/p&gt;
&lt;p&gt;If you converted this to tokens, you’d probably need four tokens to fill out the inner/outer and light/dark matrix. But I’d consider not using custom color tokens for focus-rings at all and embrace the higher contrast… or limit tokens to the outer-ring.&lt;/p&gt;
</description>
        <pubDate>Sun, 11 Jan 2026 18:30:00 +0000</pubDate>
        <link>https://daverupert.com/2026/01/nested-contrast-color-focus-rings/</link>
        <guid isPermaLink="true">https://daverupert.com/2026/01/nested-contrast-color-focus-rings/</guid>
      </item>
    
      <item>
        <title>Interpolate contrast-color() to manipulate lightness</title>
        <description>&lt;p&gt;In &lt;a href=&quot;https://daverupert.com/2026/01/algorithmic-hover-states-with-contrast-color/&quot;&gt;my first post on &lt;code&gt;contrast-color()&lt;/code&gt;&lt;/a&gt; I demo’d using &lt;code&gt;color-mix()&lt;/code&gt; to change a background-color on hover, but I will be honest… mixing black and white isn’t always what you want. It would be cool and helpful to coerce  &lt;code&gt;contrast-color()&lt;/code&gt; to return either &lt;code&gt;1&lt;/code&gt; or &lt;code&gt;-1&lt;/code&gt; so that we could adjust lightness in a color function on hover instead of only mixing white and black.&lt;/p&gt;
&lt;p&gt;Building on the inline CSS &lt;code&gt;if()&lt;/code&gt; statements &lt;a href=&quot;https://daverupert.com/2026/01/contrast-color-with-custom-design-tokens/&quot;&gt;in my last post&lt;/a&gt;, we can use the same trick to interpolate the result of &lt;code&gt;contrast-color()&lt;/code&gt; into a number.&lt;/p&gt;
&lt;p&gt;&lt;small&gt;Disclaimer: All caveats from the previous post about browser support, caching quirks, and expected syntax changes still apply.&lt;/small&gt;&lt;/p&gt;
&lt;p class=&quot;codepen&quot; data-height=&quot;500&quot; data-default-tab=&quot;result&quot; data-slug-hash=&quot;myPogBv&quot; data-pen-title=&quot;contrast-color() powered design system colors &quot; data-user=&quot;davatron5000&quot; style=&quot;height: 500px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;&quot;&gt;
      &lt;span&gt;See the Pen &lt;a href=&quot;https://codepen.io/davatron5000/pen/myPogBv&quot;&gt;
  contrast-color() powered design system colors &lt;/a&gt; by Dave Rupert (&lt;a href=&quot;https://codepen.io/davatron5000&quot;&gt;@davatron5000&lt;/a&gt;)
  on &lt;a href=&quot;https://codepen.io&quot;&gt;CodePen&lt;/a&gt;.&lt;/span&gt;
      &lt;/p&gt;
      &lt;script async src=&quot;https://public.codepenassets.com/embed/index.js&quot;&gt;&lt;/script&gt;
&lt;p&gt;Ahh… feel that? Now our states maintains its harmonious color palette where mixing in white or black gets us a bit muddier results. We’re picking another note on the scale of the color’s lightness ramp.&lt;/p&gt;
&lt;p&gt;The relevant CSS to make this trick work goes like this:&lt;/p&gt;
&lt;div class=&quot;language-css highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code data-lang=&quot;css&quot;&gt;&lt;span class=&quot;c&quot;&gt;/* Needed for if() statement */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@property&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;--captured-color&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;py&quot;&gt;syntax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&quot;&amp;lt;color&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;py&quot;&gt;inherits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;py&quot;&gt;initial-value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;white&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;/* https://lea.verou.me/blog/2024/contrast-color/ */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;--contrast-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--bg-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;py&quot;&gt;--l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;clamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--l-threshold&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0.623&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;-infinity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;py&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oklch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--bg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--ds-button-bg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;py&quot;&gt;--captured-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;--contrast-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--ds-button-bg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
  &lt;span class=&quot;py&quot;&gt;--lighter-or-darker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--captured-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oklch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)):&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;/* go extra lighter */&lt;/span&gt;
    &lt;span class=&quot;py&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;-1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;/* go darker */&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;);&lt;/span&gt;  
  &lt;span class=&quot;err&quot;&gt;...&lt;/span&gt;
  
	&lt;span class=&quot;err&quot;&gt;&amp;amp;:hover,&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;&amp;amp;:focus&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;nl&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oklch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--ds-button-bg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
			&lt;span class=&quot;n&quot;&gt;calc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0.1&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--lighter-or-darker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;h&lt;/span&gt; 
		&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;For comparison’s sake, I web-inspected up a little apples-to-apples, side-by-side of the &lt;a href=&quot;https://cdpn.io/pen/debug/myPogBv&quot;&gt;adjusting lightness way&lt;/a&gt; and the &lt;a href=&quot;https://cdpn.io/pen/debug/bNpzYzX&quot;&gt;color-mixing way&lt;/a&gt; of algorithmic hover states where it’s 10% lightened/darkened versus 10% mix of white/black.&lt;/p&gt;
&lt;img src=&quot;https://cdn.daverupert.com/posts/2026/colormixing.png&quot; alt=&quot;a side by side look at adjusting lightness vs mixing in white and black. the rest for all the buttons is on top and the hover state for all the buttons is on the bottom. The hover states for the buttons on the adjusting lightness demo are a bit warmer, but probably hard to notice to the average person.&quot;&gt;
&lt;p&gt;The difference is almost imperceptible, but the hover states from the “Adjust Lightness” method feel a tad bit warmer, particularly on the bottom row with the green, blue, and purple buttons. The difference becomes more obvious if the step is greater than 10%.&lt;/p&gt;
&lt;p&gt;Unless your customers are a bunch of color dorks, they probably won’t see it the care you put into this. But I’m willing to wager that even if they don’t see the difference, they will be able to feel the difference.&lt;/p&gt;
&lt;p&gt;We also get a lot more control with this &lt;code&gt;if()&lt;/code&gt; statement route. For example, I can set the lighten amount to &lt;code&gt;2.5&lt;/code&gt; (+25%) instead of &lt;code&gt;1&lt;/code&gt; (+10%) because that’s what felt better. If you’re algorithmically generating your color palettes, it should be easy to find the ideal values; either a step-up or step-down, perhaps. And we’re also not just limited to lightness! You could mess with chroma or whatever the &lt;code&gt;b&lt;/code&gt; in &lt;code&gt;lab()&lt;/code&gt; is. Find what makes sense for your system.&lt;/p&gt;
&lt;p&gt;A part of me wants to take this even further to get more control. For example, if the color is super dark (e.g. black) and the lightness value is below &lt;code&gt;0.1&lt;/code&gt;, lighten by 25%, otherwise lighten by 10%. That might be possible with an &lt;code&gt;if()&lt;/code&gt; inside the &lt;code&gt;oklch()&lt;/code&gt; or a &lt;code&gt;sin()&lt;/code&gt; function… but that sounds like a lot of Math and probably hurts readability. More experiments to do though.&lt;/p&gt;
&lt;p&gt;It’s fun to embark on this new world of algorithmic color schemes in vanilla CSS. While I’m excited to play, I’m more excited to see what your beautiful brains come up with.&lt;/p&gt;
</description>
        <pubDate>Fri, 09 Jan 2026 15:35:00 +0000</pubDate>
        <link>https://daverupert.com/2026/01/coercing-contrast-color/</link>
        <guid isPermaLink="true">https://daverupert.com/2026/01/coercing-contrast-color/</guid>
      </item>
    
      <item>
        <title>Using your design system colors with contrast-color()</title>
        <description>&lt;p&gt;One predictable pain point with &lt;code&gt;contrast-color()&lt;/code&gt; is that it only returns &lt;code&gt;black&lt;/code&gt; and &lt;code&gt;white&lt;/code&gt; named colors. From a design systems perspective, that’s not ideal because you want &lt;em&gt;your&lt;/em&gt; colors. You want your harmonious brand and the colors you and your team spent thousands of man hours in meetings deciding on. Those colors.&lt;/p&gt;
&lt;p&gt;In fact, &lt;a href=&quot;https://css-tricks.com/exploring-color-contrast-for-the-first-time/&quot;&gt;an earlier version of Safari had &lt;code&gt;color-contrast()&lt;/code&gt;&lt;/a&gt; (confusing I know, naming is hard) which allowed you to pass in a list of best candidates to choose from. I beleive that proposal got mired in standards discussions, color contrast algorithms, and competing proposals; and &lt;code&gt;contrast-color()&lt;/code&gt; is what survived which got simplified down to a binary result.&lt;/p&gt;
&lt;p&gt;In the future though, we can use &lt;code&gt;contrast-color()&lt;/code&gt; and &lt;code&gt;if()&lt;/code&gt; together to help pick the value we want. Alas, at the time of writing no browser supports both &lt;code&gt;if()&lt;/code&gt; and &lt;code&gt;contrast-color()&lt;/code&gt;.  But we can use &lt;a href=&quot;https://lea.verou.me/blog/2024/contrast-color/&quot;&gt;Lea Verou’s &lt;code&gt;--contrast-color()&lt;/code&gt; workaround&lt;/a&gt; to experiment with how this will work in Chromium today.&lt;/p&gt;
&lt;p class=&quot;codepen&quot; data-height=&quot;500&quot; data-default-tab=&quot;result&quot; data-slug-hash=&quot;myPogBv&quot; data-pen-title=&quot;contrast-color() powered design system colors &quot; data-user=&quot;davatron5000&quot; style=&quot;height: 500px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;&quot;&gt;
      &lt;span&gt;See the Pen &lt;a href=&quot;https://codepen.io/davatron5000/pen/myPogBv&quot;&gt;
  contrast-color() powered design system colors &lt;/a&gt; by Dave Rupert (&lt;a href=&quot;https://codepen.io/davatron5000&quot;&gt;@davatron5000&lt;/a&gt;)
  on &lt;a href=&quot;https://codepen.io&quot;&gt;CodePen&lt;/a&gt;.&lt;/span&gt;
      &lt;/p&gt;
      &lt;script async src=&quot;https://public.codepenassets.com/embed/index.js&quot;&gt;&lt;/script&gt;
&lt;p&gt;The CSS to get this working looks something like this:&lt;/p&gt;
&lt;div class=&quot;language-css highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code data-lang=&quot;css&quot;&gt;&lt;span class=&quot;k&quot;&gt;@property&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;--captured-color&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;py&quot;&gt;syntax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&quot;&amp;lt;color&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;py&quot;&gt;inherits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;py&quot;&gt;initial-value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;white&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;/* https://lea.verou.me/blog/2024/contrast-color/ */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;--contrast-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--bg-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;py&quot;&gt;--l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;clamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--l-threshold&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0.623&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;-infinity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;py&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oklch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--bg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;:root&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;py&quot;&gt;--ds-text-white&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;wheat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;py&quot;&gt;--ds-text-black&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;darkslategray&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--ds-button-bg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;py&quot;&gt;--captured-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;--contrast-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--ds-button-bg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
  
  &lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
     &lt;span class=&quot;n&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--captured-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oklch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)):&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--ds-text-white&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
     &lt;span class=&quot;py&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--ds-text-black&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;And that’s it! Using (a form of) &lt;code&gt;contrast-color()&lt;/code&gt; you can select the proper tokens from your design system. Cool.&lt;/p&gt;
&lt;p&gt;One quirky bit needed to make it work is defining a type for &lt;code&gt;--captured-color&lt;/code&gt; using CSS &lt;code&gt;@property&lt;/code&gt;, &lt;a href=&quot;https://blog.kizu.dev/captured-custom-properties/&quot;&gt;a trick I learned from Roma Komarov&lt;/a&gt;. To be honest I don’t fully understand &lt;em&gt;the why&lt;/em&gt; behind Registered Custom Properties and the &lt;a href=&quot;https://drafts.css-houdini.org/css-properties-values-api/#calculation-of-computed-values&quot;&gt;Computed Value Time Behavior&lt;/a&gt; superpower, but my simple brain created a rule “If you’re going to compare a variable to a &lt;code&gt;&amp;lt;color&amp;gt;&lt;/code&gt; in a CSS &lt;code&gt;if()&lt;/code&gt; statement, make sure to register the variable as a &lt;code&gt;&amp;lt;color&amp;gt;&lt;/code&gt;.”&lt;/p&gt;
&lt;p&gt;If/when any of the browsers start supporting both features, I expect we’ll have to update &lt;code&gt;oklch(1 0 0)&lt;/code&gt; in the style query to &lt;code&gt;white&lt;/code&gt; or &lt;code&gt;rgb(255 255 255)&lt;/code&gt;.  At least, I hope it works that way.&lt;/p&gt;
&lt;p&gt;One unexpected challenge that I encountered with this demo was that if I abstracted out the &lt;code&gt;if&lt;/code&gt; statement out into its own custom function, it would break. I’m not 100% sure why but I think it’s based on how CSS functions cache results. I’ll have to dig into this more, but I’m happy the inline &lt;code&gt;if&lt;/code&gt; statement works. Hopefully someone smarter can figure it out.&lt;/p&gt;
&lt;p&gt;Anyways, exiting times. And can we pause for a moment and marvel at how this is all vanilla 2026 CSS?! What a world.&lt;/p&gt;
</description>
        <pubDate>Fri, 09 Jan 2026 03:21:00 +0000</pubDate>
        <link>https://daverupert.com/2026/01/contrast-color-with-custom-design-tokens/</link>
        <guid isPermaLink="true">https://daverupert.com/2026/01/contrast-color-with-custom-design-tokens/</guid>
      </item>
    
      <item>
        <title>Algorithmic hover states with contrast-color()</title>
        <description>&lt;p&gt;Firefox 146 added support for &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/color_value/contrast-color&quot;&gt;&lt;code&gt;contrast-color()&lt;/code&gt;&lt;/a&gt; joining Safari 26 in the First Implementor’s Club. For those unfamiliar, &lt;code&gt;contrast-color(&amp;lt;color&amp;gt;)&lt;/code&gt;  is a new CSS function that will take a &lt;code&gt;&amp;lt;color&amp;gt;&lt;/code&gt; as input and returns either  &lt;code&gt;white&lt;/code&gt; or &lt;code&gt;black&lt;/code&gt; depending on which has the most contrast.&lt;/p&gt;
&lt;p&gt;The quintessential example is choosing a foreground text &lt;code&gt;color&lt;/code&gt;  with the best contrast.&lt;/p&gt;
&lt;div class=&quot;language-css highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code data-lang=&quot;css&quot;&gt;&lt;span class=&quot;nt&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;py&quot;&gt;--button-bg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;red&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;nl&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--button-bg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contrast-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--button-bg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt; 
	&lt;span class=&quot;c&quot;&gt;/* @returns black (5.25:1 WCAG AA Pass) 
			not white (3.99:1 WCAG AA Fail) */&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;If someone changes &lt;code&gt;--button-bg&lt;/code&gt; to purple, the foreground color automatically resolves to the either white or black, whichever has more contrast. It avoids having to set an extra token for color and takes the guess work out of picking an accessible foreground color.&lt;/p&gt;
&lt;p&gt;I think this is going to be an incredible boon to design systems where I don’t control what &lt;code&gt;--button-bg&lt;/code&gt; is, but I do care about providing accessible experiences. And I think that’s the goal of this feature; to have “smart defaults” that lead to more accessible websites, easier algorithmically-driven color systems, and better “theme a whole website from a single color picker” demos.&lt;/p&gt;
&lt;h2&gt;Sure contrast-color() can do foreground colors, but what about backgrounds?&lt;/h2&gt;
&lt;p&gt;We’re having conversations at work about algorithmically driven rest/hover/active states for Buttons. In the current &lt;a href=&quot;https://web.dev/baseline/&quot;&gt;Baseline&lt;/a&gt; you can use &lt;code&gt;color-mix()&lt;/code&gt; to lighten/darken colors on &lt;code&gt;:hover&lt;/code&gt;…&lt;/p&gt;
&lt;div class=&quot;language-css highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code data-lang=&quot;css&quot;&gt;&lt;span class=&quot;nt&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;nl&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--button-bg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contrast-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--button-bg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;

	&lt;span class=&quot;err&quot;&gt;&amp;amp;:hover,&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;&amp;amp;:focus&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;nl&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color-mix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;srgb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--button-bg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;90%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
			&lt;span class=&quot;no&quot;&gt;black&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;10%&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The code above will dim your button on &lt;code&gt;:hover&lt;/code&gt; 10% by mixing in black. But what if our Buttons are already dark (black, navy, etc)? In that situation we want to lighten the background-color instead of dimming. We can glue on new classes like &lt;code&gt;button.lighten-on-hover&lt;/code&gt; or &lt;code&gt;button.invert-hover&lt;/code&gt; and that works… until we get to light and dark theme modes of our Button where you probably want to lighten/darken oppositely depending on the mode…&lt;/p&gt;
&lt;p&gt;Ugh. In that situation you’d have &lt;code&gt;@media (prefers-color-scheme: dark)&lt;/code&gt;, &lt;code&gt;[data-theme=&amp;quot;dark&amp;quot;]&lt;/code&gt; styles in your Button styles and people are mad now because the Button styles are too complex. There’s got to be a better way!&lt;/p&gt;
&lt;p&gt;Well, do I have good news for you…&lt;/p&gt;
&lt;p class=&quot;codepen&quot; data-height=&quot;500&quot; data-default-tab=&quot;result&quot; data-slug-hash=&quot;bNpzYzX&quot; data-pen-title=&quot;contrast-color() powered lighten/darken bg on hover &quot; data-user=&quot;davatron5000&quot; style=&quot;height: 500px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;&quot;&gt;
      &lt;span&gt;See the Pen &lt;a href=&quot;https://codepen.io/davatron5000/pen/bNpzYzX&quot;&gt;
  contrast-color() powered lighten/darken bg on hover &lt;/a&gt; by Dave Rupert (&lt;a href=&quot;https://codepen.io/davatron5000&quot;&gt;@davatron5000&lt;/a&gt;)
  on &lt;a href=&quot;https://codepen.io&quot;&gt;CodePen&lt;/a&gt;.&lt;/span&gt;
      &lt;/p&gt;
      &lt;script async src=&quot;https://public.codepenassets.com/embed/index.js&quot;&gt;&lt;/script&gt;
&lt;p&gt;Per my previous conversations, I wondered if we could use &lt;code&gt;contrast-color()&lt;/code&gt;  to programmatically lighten/darken an button based on its current &lt;code&gt;background-color&lt;/code&gt;. If the Button is black, and the contrast-color is white, let’s mix in white (and vice versa):&lt;/p&gt;
&lt;div class=&quot;language-css highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code data-lang=&quot;css&quot;&gt;&lt;span class=&quot;nd&quot;&gt;:root&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;py&quot;&gt;color-scheme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;light&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;py&quot;&gt;--button-bg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;light-dark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;navyblue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lightpurple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;nl&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--button-bg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color-contrast&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--button-bg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;

	&lt;span class=&quot;err&quot;&gt;&amp;amp;:hover,&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;&amp;amp;:focus&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;nl&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color-mix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;srgb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--button-bg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;75%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
			&lt;span class=&quot;n&quot;&gt;contrast-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--button-bg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;10%&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Huzzah! Now our Button’s hover states go in the desired direction and our foreground &lt;code&gt;color&lt;/code&gt; is intrinsically styled based on its own &lt;code&gt;background-color&lt;/code&gt;. Nice. From a design systems perspective I’m pretty excited about the possibility to remove a bunch of state-based tokens from our collection.&lt;/p&gt;
&lt;h3&gt;Now available in… everywhere?&lt;/h3&gt;
&lt;p&gt;This approach only works in Safari and Firefox. However, if I use &lt;a href=&quot;https://lea.verou.me/blog/2024/contrast-color/&quot;&gt;Lea Verou’s method of polyfilling &lt;code&gt;contrast-color()&lt;/code&gt;&lt;/a&gt;, we can pop in a custom &lt;code&gt;@function --contrast-color()&lt;/code&gt; that works in Chromium 139+. The final working solution looks like this:&lt;/p&gt;
&lt;div class=&quot;language-css highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code data-lang=&quot;css&quot;&gt;&lt;span class=&quot;c&quot;&gt;/* @function supported in Chromium */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;--contrast-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--bg-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;py&quot;&gt;--l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;clamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--l-threshold&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0.623&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;-infinity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;py&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oklch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--bg-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;/* contrast-color() supported in Safari &amp;amp; Firefox */&lt;/span&gt;
  &lt;span class=&quot;py&quot;&gt;--button-fg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contrast-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--button-bg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
  
  &lt;span class=&quot;err&quot;&gt;@supports&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contrast-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;red&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;--button-fg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;--contrast-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--button-bg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;nt&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--button-bg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--button-fg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  
  &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;:hover&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;:focus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color-mix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;srgb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--button-bg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;75%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;--button-fg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;10%&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Depending on your browser matrix, this may work for you. It’s probably a &lt;em&gt;smidge&lt;/em&gt; too new for us to roll out to customers, right now but for personal sites heck yeah.&lt;/p&gt;
&lt;p&gt;This is interesting tech and I’m excited to dig in more. And spoiler alert, this is the first post in a small little series I have already written up for you.&lt;/p&gt;
</description>
        <pubDate>Thu, 08 Jan 2026 16:46:00 +0000</pubDate>
        <link>https://daverupert.com/2026/01/algorithmic-hover-states-with-contrast-color/</link>
        <guid isPermaLink="true">https://daverupert.com/2026/01/algorithmic-hover-states-with-contrast-color/</guid>
      </item>
    
      <item>
        <title>Twenty Twenty-Five</title>
        <description>&lt;p&gt;2025 was… a year. And I made it to the end of that year. If you’re reading this, I imagine you did too and let’s celebrate that. But also not one without loss; of loved ones, of health, of relationships, of jobs, of liberties, of pursuits of happiness. Let’s mourn those.&lt;/p&gt;
&lt;p&gt;My year was mundane by most accounts. I worked, I family’d, and with the remaining life force I focused on myself. A couple failed side projects and half-baked game ideas in there but welcomingly “unproductive” relative to what I normally subject myself to. On a handful of fronts this year has been about scaling back in what I burden myself with, in material posessions, in finances, in obligations, and elsewhere. Ideally, I can clear the plate of duties that demand my limited attention. To be so bored that I read a magazine.&lt;/p&gt;
&lt;h2&gt;Resolutions resolved&lt;/h2&gt;
&lt;p&gt;I set some slightly different goals last year. Let’s check on last year’s goals:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;🟢 &lt;strong&gt;Seize work opportunities&lt;/strong&gt; - I’ll call this a success. Released a design system and token system. An executive-level mandate caused us to pivot the entire design language using the tokens. Success. Other big products are beginning to use our team’s work, we’re recognized for the accessibility of our product… which is great.&lt;/li&gt;
&lt;li&gt;🔴 &lt;strong&gt;Hunker down and be creative&lt;/strong&gt; - In the interest of binaries, I’ll say no. I think I gravitated to work and mind-numbing recovery, not creativity. I wasn’t very productive beyond work and family life. I think given “the situation” in the homeland, that’s okay.&lt;/li&gt;
&lt;li&gt;🟠  &lt;strong&gt;Slow down to 1x mode&lt;/strong&gt; - I still watch and listen way too much in 2x but at a certain point it does feel natural. Certain content gets the 1x treatment, but not enough. I did slow down though, generally speaking. Less books, less blog posts, less side projects. And that’s okay.&lt;/li&gt;
&lt;li&gt;🔴 &lt;strong&gt;Join a club&lt;/strong&gt; - I made attempts to join two different writing clubs, but it didn’t work out. One met on an inconvenient night and I guess I failed the application for the other one. I joined a Discord for a Gunpla group… but never went. Closest I got to joining a club is a dad band that plays after our kids’ band practices.&lt;/li&gt;
&lt;li&gt;🟢 &lt;strong&gt;Understand myself&lt;/strong&gt; - I’m progressing on my health journey to untangle the knot of anxiety, weight, and ADHD. I’ve done all the important appointments and follow-ups. I’ve done the diet. I’ve done the exercise. I’ve got new medications all lined up. Waiting for something to change.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A month-by-month breakdown&lt;/h2&gt;
&lt;ul class=&quot;calendar&quot;&gt;
&lt;li&gt;&lt;strong&gt;Jan&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;New pain meds&lt;/li&gt;
&lt;li&gt;New ADHD meds&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Feb&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Launched internal design system&lt;/li&gt;
&lt;li&gt;Shipped cross-product/platform token system&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mar&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Landscaping project&lt;/li&gt;
&lt;li&gt;Trip to Arizona&lt;/li&gt;
&lt;li&gt;Renaissance Faire&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Apr&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Cheer competition in New Orleans&lt;/li&gt;
&lt;li&gt;New car&lt;/li&gt;
&lt;li&gt;45th Birthday&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;May&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;New ADHD meds&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Jun&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Trip to Grand Canyon&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Jul&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Shipped design system redesign&lt;/li&gt;
&lt;li&gt;Trip to San Diego&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Aug&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Back to school&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sept&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Volunteered at Austin-Oita 夏祭り&lt;/li&gt;
&lt;li&gt;New BP meds&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Oct&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Trip to Santa Barbara&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Nov&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;The Beths&lt;/li&gt;
&lt;li&gt;Rainer Maria and Cap’n Jazz&lt;/li&gt;
&lt;li&gt;Launched Grid-Paper&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dec&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;New BP meds&lt;/li&gt;
&lt;li&gt;New GLP-1 meds&lt;/li&gt;
&lt;li&gt;Christmas in Nebraska&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The school rush and kid activities fill most non-working hours. It’s a lot of work right now but we signed up for it by having children. Speaking of children, my daughter’s cheer team won a national championship, which is an incredible accomplishment and experience for her. And my son started playing guitar this year which makes the whole family happy. Both kids are 10+ now which feels like we’re entering a new era in parenting; more autonomy, different problems, deeper conversations, movies with curse words, and more attitude. It’s new territory.&lt;/p&gt;
&lt;h2&gt;An average amount of books&lt;/h2&gt;
&lt;p&gt;I had a sub-goal of reading less this year and I succeeded! That feels good.&lt;/p&gt;
&lt;div class=&quot;gallery&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/1541788516.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;A Libertarian Walks Into a Bear&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/1668035359.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;It&apos;s Only Drowning&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/1982149140.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;Control Freak&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/1662602723.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;Slow Down&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/B0FLTLP4WK.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;Fight Oligarchy&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/B003F3FJGY.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;At Home&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/B0CGKL5FGF.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;Extra Focus&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/1668066890.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;Separation of Church and Hate&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/1506741401.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;H.P. Lovecraft&apos;s The Call of Cthulhu&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/0063051338.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;Sapiens&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/1439148813.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;Failure Is Not an Option&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/0063418568.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;The AI Con&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/B08R2KL3VY.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;The Dawn of Everything&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/B09TYQNFFG.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;Win Every Argument&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/031658035X.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;Moral Ambition&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/B0F659XPN2.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;Dungeon Crawler Carl&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/0593728696.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;A Different Kind of Power&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/1647397057.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;ADHD and Us&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/1555976042.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;Red Plenty&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/1626929122.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;Space Battleship Yamato&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/1541703340.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;The Wrong Stuff&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/B0DHZ2ZXPM.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;Who is Government?&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/1250397677.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;Mediations for Mortals&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/1668023482.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;Abundance&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/0593239938.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;Poverty, by America&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/1250391237.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;Careless People&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/1250826977.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;System Collapse&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/0307720454.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;Twilight of the Elites&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/0593653114.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;The Sirens&apos; Call&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/1250765374.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;Fugitive Telemetry&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/1101972084.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;Exhalation&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/0307888908.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;The Startup of You&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/1400247268.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;The Customer Is Always Wrong&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/1400226678.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;Disrupting the Game&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/081298160X.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;The Power of Habit&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/1591845637.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;Super Mario&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/1847943748.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;Feel Good Productivity&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/0061176044.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;Being Wrong&quot;&gt;
&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/1250229855.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;Network Effect&quot;&gt;
&lt;/div&gt;
&lt;p&gt;I encountered a lot of mediocre books this year but there were some bangers in there like &lt;a href=&quot;https://amzn.to/45g0s5b&quot;&gt;The Dawn of Everything&lt;/a&gt;, &lt;a href=&quot;https://amzn.to/3SZMflH&quot;&gt;The Wrong Stuff&lt;/a&gt;, and &lt;a href=&quot;https://amzn.to/3YEqwTD&quot;&gt;The Sirens’ Call&lt;/a&gt;. It’s possible I’ve maxed out on books though. My appetite to seek out new books to read in the last two months has been super low. They’re all starting to blur into a large mush. I have a backlog of manga to read… perhaps next year is the year I get back into comics?&lt;/p&gt;
&lt;h2&gt;An average amount of blogging&lt;/h2&gt;
&lt;p&gt;I published 53 posts in 2025 which averages to a post-a-week, but there’s some hot streaks in there skewing the stats. It’s less than the year before which (again) I’ll count as a win. Behind the scenes there’s dozens of half-finished posts, but it takes so much effort to finish a technical post about CSS or web components who knows when those will see the light of day.&lt;/p&gt;
&lt;p&gt;Here’s a smattering of posts that either made the rounds or I’m proud of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CSS Tricks
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://daverupert.com/2025/08/git-diagramming-the-weave/&quot;&gt;Git diagramming “The Weave”&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://daverupert.com/2025/07/sci-fi-rectangles-with-corner-shape/&quot;&gt;Easy sci-fi rectangles with corner-shape&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://daverupert.com/2025/06/fittext-too-attr-boogaloo/&quot;&gt;Inverse text-sizing based on text-length with attr()&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://daverupert.com/2025/01/color-hue-rotating-gaslight/&quot;&gt;My website has been gaslighting you&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Web Components
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://daverupert.com/2025/10/custom-elements-manifest-killer-feature/&quot;&gt;The killer feature of Web Components&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://daverupert.com/2025/10/quiet-ui/&quot;&gt;Lots to shout about in Quiet UI&lt;/a&gt; (RIP)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Misc.
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://daverupert.com/2025/09/why-would-anybody-start-a-website/&quot;&gt;“Why would anybody start a website?”&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://daverupert.com/2025/10/why-i-hate-the-mvp-car/&quot;&gt;Why I hate the MVP car&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://daverupert.com/2025/09/you-cant-drink-coffee-on-a-running-horse/&quot;&gt;Many years on the job and I still don’t get it.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://daverupert.com/2025/08/classifiers-and-cosmotechnics/&quot;&gt;Classifiers and cosmotechnics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://daverupert.com/2025/08/got-99-engineering-problems-but-a-grift-aint-one/&quot;&gt;All the concerns that make you a boring developer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://daverupert.com/2025/07/always-buy-the-yamaha/&quot;&gt;Before I go: Always buy the $200 Yamaha&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://daverupert.com/2025/07/social-media-ethos/&quot;&gt;A social media ethos&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I’m sure I left something out but no need to overthink it. You can &lt;a href=&quot;https://daverupert.com/archive/&quot;&gt;peruse the archive&lt;/a&gt; if you want.&lt;/p&gt;
&lt;h2&gt;Living in the zone of shit&lt;/h2&gt;
&lt;p&gt;American politics drove a lot of my daily vibes this year. Day-after-day of bullshit executive orders, tariffs, lies, DOGE, fuckups, coverups, corruption, kidnappings, gulags, military occupation of democratic US cities under false pretenses, murders at sea, billionaires, institutional collapse, and everything else is exhausting. The economic anxiety weighed heavily on me; we even panic bought a car! But watching groceries get more expensive, budgets get tighter, all while the President and his cronies launch crypto grifts to launder money from billionaires and foreign governments in an open influence peddling scheme is infuriating.&lt;/p&gt;
&lt;p&gt;I had to step back from news a bit for my own mental health, but also it’s getting repetitive. Regime does stupid/illegal thing, PERSON gets DESTROYED by THING (but never does), consequences never happen, the world is unjust. I &lt;em&gt;know&lt;/em&gt; the strategy is to exhaust, but I hit peak outrage years ago and this feels like a long, unshakable hangover of bad decisions. My trust in any form of government erodes like sand cliffs.&lt;/p&gt;
&lt;p&gt;Mix in a highly speculative tech hype cycle which makes up a disproportionate amount of the economy and stock market valuation… and it’s hard to shake off a sense of dread.&lt;/p&gt;
&lt;h2&gt;Focusing on my physical and mental health&lt;/h2&gt;
&lt;p&gt;All my extra spoons went to wrangling my physical and mental health. Sometimes that manifested as staring at an iPad on my recliner after long day at work, but it also involved a lot of doctors visits. This has been a year and a half long journey (since good healthcare kicked in) of prioritizing myself. And while the news isn’t all great, I’m getting a clearer picture of the brain and body I’m dealing with. There’s a long road ahead and I don’t actually know when/if it gets better, but having a pathway forward means a lot right now.&lt;/p&gt;
&lt;p&gt;I was unconsolably grumpy for nearly two months straight. It could be burnout. It could be cheese-moving. It could be depression manifesting differently. What I learned from going through that spell was &lt;strong&gt;good people and great music are the secret to being happy&lt;/strong&gt;. At least for me. And I need to make sure I’m building that into the regular rhythms of my life.&lt;/p&gt;
&lt;h2&gt;2026: No New Projects&lt;/h2&gt;
&lt;p&gt;Next year has the potential to be good. If a certain elderly statesman, for example, passed away from age-related illnesses… that might change the mood considerably. But speaking to what’s within my sphere of control, I think there’s capacity for goodness.&lt;/p&gt;
&lt;p&gt;For 2026, I’m adopting a mantra of “No new projects.” There will be new projects of course; they fit all the interest, novelty, challenge, urgency, and passion (INCUP) requirements that motivate ADHD brains. The spirit of “No new projects” is to finish more projects than I start. In the last month or so I’ve been aggressive on closing out old lingering to-dos; home improvements, organizing, taxes, managing devices, etc. and I want to continue that work of clearing out all those nagging unfinished bits. I want to buy back precious Brain RAM so I feel less overwhelmed all the time.&lt;/p&gt;
&lt;p&gt;“No new projects” helps me be more present and realize when I’m creating work for myself. When I buy a new device, or an instrument, or think about building my own home server array… “No new projects” puts a hurdle in the way of that decision so that I don’t DDoS myself with a backlog of small jobs pursuing an impulse.&lt;/p&gt;
&lt;p&gt;I tend to externalize, but 2026 also feels highly dependent on what happens in tech in the next year. A change in my job? A robot taking my job? A mass layoff? A bubble bursting? An industry collapse? A retreat to a smaller web? A new and unexpected technological breakthrough? As I hinted earlier, it feels like the entirety of tech has hitched itself to a highly speculative bet and we all have to wait and see what happens. The lack of clarity and concrete vision for the future of human-centered computing and labor creates a feeling of insecurity for me. A trillion dollar hurricane. Displacement.&lt;/p&gt;
&lt;p&gt;But we can write. And we can dream. And we can imagine a future where humans connect.&lt;/p&gt;
</description>
        <pubDate>Fri, 02 Jan 2026 06:08:00 +0000</pubDate>
        <link>https://daverupert.com/2026/01/twenty-twenty-five/</link>
        <guid isPermaLink="true">https://daverupert.com/2026/01/twenty-twenty-five/</guid>
      </item>
    
      <item>
        <title>Vibe Check №41</title>
        <description>&lt;p&gt;🎵 Christmas time is here. Happiness and cheer. Fun for all… that children call… their favorite time of year.&lt;/p&gt;
&lt;p&gt;School’s out. The work laptop’s closed. Now is a good time to recount the vibes. I wanted to get out this vibecheck before embarking on the annual recap that way it’s less moodier than years prior.&lt;/p&gt;
&lt;h2&gt;Fixing my mood with music&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://daverupert.com/2025/10/vibe-check-40/&quot;&gt;Last vibe check&lt;/a&gt; I was super grumpy. Thankfully, I was able to start shaking off that cloud by fixing my mood with music. I am not kidding when I say I got to see three of my favorite bands in the span of a month.&lt;/p&gt;
&lt;img src=&quot;https://cdn.daverupert.com/posts/2025/thebeths.jpg&quot; alt=&quot;the beths on stage&quot; width=&quot;1200&quot; height=&quot;675&quot; style=&quot;border-radius: 12px;&quot;&gt;
&lt;p&gt;The first was my current favorite band &lt;a href=&quot;https://www.thebeths.com/&quot;&gt;The Beths&lt;/a&gt;. According to Spotify Wrapped I’m a Top 0.2% global fan. They came through Austin and played an incredible set at Emo’s. All the hits. I was enchanted for one evening.&lt;/p&gt;
&lt;p&gt;Then a week or so later I saw my friend Richard’s band &lt;a href=&quot;https://rlkentopp.bandcamp.com/album/rainbow&quot;&gt;Heartswarm&lt;/a&gt; play at The Aristocrat. I have a lot of friends who play music and in a town like Austin I was feeling remorse for not enjoying that more at every chance I get.&lt;/p&gt;
&lt;p&gt;Then, a couple nights later, I saw one of my all time favorite emo bands when &lt;a href=&quot;https://rainermaria.bandcamp.com/&quot;&gt;Rainer Maria&lt;/a&gt; open for my other absolute most favorite (midwest) emo band &lt;a href=&quot;https://www.capnjazz.band/&quot;&gt;Cap’n Jazz&lt;/a&gt;. The show was so great and the audience was an even 50/50 split between dads over 45 and queer kids under 21. What a cross-section of society! And because my friend Richard is friends with &lt;a href=&quot;https://en.wikipedia.org/wiki/Mike_Kinsella&quot;&gt;Mike Kinsella&lt;/a&gt;, I got to hang out with the him a bit. Cool dude and an honor to finally meet in person.&lt;/p&gt;
&lt;p&gt;A couple weeks after that, I took my son and his friend to their first hardcore punk show featuring &lt;a href=&quot;https://dark-thoughts.bandcamp.com/album/highway-to-the-end&quot;&gt;Dark Thoughts&lt;/a&gt; opening for &lt;a href=&quot;https://betonarmeoimtl.bandcamp.com/&quot;&gt;Béton Armé&lt;/a&gt;. First time hearing all these bands but Dark Thoughts was awesome. Béton Armé had incredible energy. But the real surprise was Houston hardcore punk/ska band Liberty &amp;amp; Justice. Being from Houston I wondered if we knew similar people in the punk scene. I didn’t summon up enough courage to ask though because it’s been decades since I lived there, but after texting some friends back home I learned the lead singer is good friends with my old neighbor and grew up in the next town over. Small world.&lt;/p&gt;
&lt;h2&gt;Coding vibes&lt;/h2&gt;
&lt;p&gt;Despite a heavy workload at work and home projects piling up, I summoned some energy to work on some coding projects at night.&lt;/p&gt;
&lt;h3&gt;A tennis app for my wife&lt;/h3&gt;
&lt;p&gt;My wife likes to obsess over tennis scores and ratings; not limited to hers and the team she captains, but for anyone she knows in the United States. She was having trouble accessing the site she uses (tennisrecord.com) and I thought we were potentially IP-banned because she uses it so much. the app is kind of a terrible user experience… so why not try to make a good one?&lt;/p&gt;
&lt;p&gt;One constraint I added to the project was that I had to vibe code it. Partly because that’s the approximate amount of spoons I had for this project, but also to practice wrangling these machines a bit better.&lt;/p&gt;
&lt;p&gt;Vibe coding was –per usual– a rollercoaster. I told it what I wanted (a multi-page Vite app that uses Netlify functions to connect to the USTA API) and it seemed to like that. The agent generated a &lt;code&gt;PRD.md&lt;/code&gt;. I read the PRD. It looked good. I made some edits. I ran the plan…&lt;/p&gt;
&lt;p&gt;It did not follow the plan. It went off and scaffolded out the entire application and most of the views. While super impressive in such a short amount of time, generally speaking, that’s not what you want? With software I find you want to step down a path iteratively and make sure you’re not repeating the same mistakes. It would benefit LLMs to maintain a tight context window instead of doing a full blow-out on the first prompt… but that’s not what LLMs do, is it? They drive down a road until it ends and tend to go overboard; they build out features you didn’t even ask for. Also worth nothing they charge per token used.&lt;/p&gt;
&lt;p&gt;For example it didn’t understand how to write and use web components. It wrote thousands of lines of JavaScript in an imperative way, which is the opposite of what I asked for and the antithesis of the web components ethos which tends to be highly declarative and template driven. After a half-dozen repeated failures I tried the prompt “Use Lit” and seemed to understand that (sometimes). I need to re-read the chatlogs because I was able to turn the corner on quality but it required a lot of hand-holding and babysitting the machine. It excelled at short tasks like “Rename X to Y” but to be honest “Find &amp;amp; Replace in Project” isn’t a hard task for me. I think where it can be good is tedious work like changing API structures (renaming functions, etc) and then extrapolating that change out to the rest of the project.&lt;/p&gt;
&lt;p&gt;Ultimately the project died in an unceremonious way when the USTA denied my application for an API key. Boo. I will never know if all those API endpoints that weren’t in the documentation actually worked or if Copilot just invented them. Also impacting the project was the fact that Quiet UI disappeared from the internet, which is a special kind of setback for doc-dependent LLMs. Oh well. I’d rank it a mixed success. I got through my personal quality-via-the-LLM barrier, but trying to corral the stateless machine wasn’t the most enjoyable experience and I didn’t ship the app.&lt;/p&gt;
&lt;h3&gt;An app for analog drawing&lt;/h3&gt;
&lt;p&gt;I loved graph paper as a kid. I used to buy giant pads of it and make scale architectural models of my house. The algorithm surfaced some cool isomorphic dungeon drawing videos for me but the process of sourcing some graph paper let me down. I wanted to print out a couple sheets of graph paper but I kept getting skeezed out by my options on image search. Low-res JPEGs with shitty logos splattered all over. No sense of how big it’d actually be when I printed it out.&lt;/p&gt;
&lt;script src=&quot;https://esm.sh/@zachleat/browser-window@1.0.12&quot; type=&quot;module&quot;&gt;&lt;/script&gt;
&lt;browser-window flush=&quot;&quot; url=&quot;https://grid-paper.daverupert.com&quot; mode=&quot;dark&quot;&gt;
&lt;img src=&quot;https://cdn.daverupert.com/posts/2025/grid-paper.jpg&quot; alt=&quot;screenshot of my grid paper app with some configurable settings in a header and a grid covering the entire background&quot; height=&quot;600&quot; width=&quot;1200&quot; style=&quot;aspect-ratio: 688 / 344;&quot;&gt;
&lt;/browser-window&gt;
&lt;p&gt;So I spent an evening making &lt;a href=&quot;http://localhost:4000/2025/11/grid-paper/&quot;&gt;my own little Grid Paper app&lt;/a&gt;. I’m pleased with the results. It supports grids, dot-grids, isomorphic grids, perspective grids, and dual-hex grids. I have a branch locally that adds normal hex grids and more fidelity but it’s a complete refactor so it’ll take some time to finish out.&lt;/p&gt;
&lt;p&gt;All said, I’m happy with the time vs effort results on this project. A couple nights worth of work.&lt;/p&gt;
&lt;h2&gt;Retrogaming&lt;/h2&gt;
&lt;p&gt;&lt;video src=&quot;https://cdn.daverupert.com/posts/2025/retrohandheld.mp4&quot; width=&quot;1280&quot; height=&quot;720&quot; muted loop autoplay playsinline controls style=&quot;border-radius: 12px;&quot;&gt;&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;I got a neat little &lt;a href=&quot;https://anbernic.com/&quot;&gt;Anbernic retro-handheld emulator&lt;/a&gt; for Christmas last year but to be honest I hadn’t played it much. The system was lacking a lot of the first-party blockbuster games I loved. Y’know what I’m talking about… the sbarro brothers, the sanics, the pokey-mens, the mega-dudes; those sorts of games.&lt;/p&gt;
&lt;p&gt;I mentioned this to a friend and he helped me… &lt;em&gt;ahem&lt;/em&gt;… backup some games I had. And that was enough of a spark to inspire me to swap out the default operating system to a custom one called &lt;a href=&quot;https://knulli.org/&quot;&gt;Knulli&lt;/a&gt; and I made it feel neat-o by installing the &lt;a href=&quot;https://www.youtube.com/watch?v=MVPUu2BWuqw&quot;&gt;Techdweeb theme&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I’m loving it so much more. I’ve been playing through a game where you capture these little critters and use them in ethically-questionable battles against other children and adults. So that’s fun and been a great way to relax that isn’t doomscrolling or YouTube rabbit holes.&lt;/p&gt;
&lt;h2&gt;Statistical Breakdown&lt;/h2&gt;
&lt;h2&gt;📖 &lt;strong&gt;Reading&lt;/strong&gt;&lt;/h2&gt;
&lt;mini-bookshelf&gt;
&lt;template shadowrootmode=&quot;open&quot;&gt;
&lt;style&gt;
:host {
  container: host / inline-size;
}
div {
  --cols: 3;
  display: grid;
  grid-template-columns: repeat(var(--cols), 1fr);
  align-items: center;
}
@container host (width &gt; 500px) {
  div { --cols: var(--cols-desktop, 5); }
}
::slotted(img) {
  max-width: 100%;
  height: auto;
  object-fit: cover;
}
&lt;/style&gt;
&lt;div&gt;&lt;slot&gt;&lt;/slot&gt;&lt;/div&gt;
&lt;/template&gt;&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/0063051338.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;Sapiens&quot;&gt;&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/B003F3FJGY.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;At Home&quot;&gt;&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/1662602723.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;Slow Down&quot;&gt;&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/1982149140.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;Control Freak&quot;&gt;&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/1668035359.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;It&apos;s Only Drowning&quot;&gt;&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/P/1541788516.01._SCLZZZZZZZ_.jpg&quot; alt=&quot;A Libertarian Walks Into a Bear&quot;&gt;&lt;/mini-bookshelf&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://amzn.to/3IwJqXT&quot;&gt;Sapiens&lt;/a&gt; ★★★½ - This book very much fits into my historical graphic novel wheelhouse. It suffers some of the common problems with the real-book-to-comic genre (long speeches, hammy conversation setups, etc) and I struggled at the beginning, but towards the middle I latched on and enjoyed it enough to get the second book from the Library… which I didn’t read. One eyebrow-raising bit is that it somewhat opens the door to “These people have different DNA”-type phrenology or supremacy narratives. Woof.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://amzn.to/47hE2Ai&quot;&gt;At Home&lt;/a&gt; DNF - I did not finish this book, but I did enjoy it. I probably prefer a more linear history lesson on a single topic, but Bill Bryson does something unique and ties together a tapestry of historical anecdotes based on common objects found in his home. I may pick this up again in the future when things slow down and my mind can wander more.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://amzn.to/3JnBqJ7&quot;&gt;Slow Down&lt;/a&gt; ★★★★½ - Comrades! Degrowth is a topic I’m interested in. How do we break away from the “always grow” cycle of Capitalism and it’s climate death march. Kōhei Saitō suggests communism, leaning on the contemporary writings of Marx that didn’t make it in Das Kapital that were focused around ecological sustainability as opposed to revolution.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://amzn.to/484PBvb&quot;&gt;Control Freak&lt;/a&gt; ★★ - I’m always up for some video game history and CliffyB’s has played a role in some of gaming’s biggest moments. The book starts with a classic nerd coming-of-age at the dawn of the internet story that is familiar, his father’s passing, but before digging into his time at Epic games, the story takes a sudden turn recounting his own sexual abuse. Then it hops back into video games like nothing happened. The book is soaked in CliffyB’s non-malignant but very apparent narcissism. Name drops. Affairs. Divorce. Matching Lambos. Markers of success CliffyB seems to wear like self-deprecating badges of honor. I don’t mean to take from CliffyB’s successes (Unreal Tournament, Gears of War, Fortnite, etc) and those portions of the book are interesting in their own right, but overall… it felt like a very personal story rather than a general nerds-to-riches type story.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://amzn.to/4jbZagQ&quot;&gt;It’s Only Drowning&lt;/a&gt; ★★★½ - Author David Litt decides to take up surfing late-in-life. To achieve this goal he must befriend his twenty-something brother-in-law. It’s a story of self-realization and challenging yourself to achieve a difficult goal as well as bridging an awkward familial/generational/political gap. I think it also embodies the male loneliness epidemic; a desire to have relationships with people who aren’t our spouse, to be invited, and to belong.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://amzn.to/4pXqQsA&quot;&gt;A Libertarian Walks Into a Bear&lt;/a&gt; &lt;small&gt;[In progress]&lt;/small&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h3&gt;📝 &lt;strong&gt;Blogging&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;I had a secret theme –that I don’t if anyone picked up on– but I was trying to share things I like. A couple got serious, but most of them were simple posts about a game or YouTube series I like. I think this also helped put me in a better moo.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;/2025/11/random-mini-dungeons/&quot;&gt;Random Mini Dungeons&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;/2025/11/ariathome/&quot;&gt;ARIatHOME&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;/2025/11/rust-storytelling/&quot;&gt;The built-in storytelling of Rust&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;/2025/11/project-kamp/&quot;&gt;Project Kamp&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;/2025/11/precious-plastic/&quot;&gt;Precious Plastic&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;/2025/11/golden-candlesticks/&quot;&gt;Golden candlesticks&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;/2025/11/la-rinconada-peru/&quot;&gt;La Rinconada, Peru&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;/2025/11/clues-by-sam/&quot;&gt;Clues by Sam&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;/2025/11/inkwell-games/&quot;&gt;Inkwell Games&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;/2025/11/grid-paper/&quot;&gt;Grid Paper&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;/2025/11/communions-and-ladders/&quot;&gt;One thing churches do well&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These posts are easier technical posts. They don’t get as many hits… but they also don’t get stuck in months-long quality assurance and demo-building limbo.&lt;/p&gt;
&lt;h3&gt;📺 Media Diet&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Movies&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://letterboxd.com/film/wake-up-dead-man/&quot;&gt;Wake Up, Dead Man&lt;/a&gt; - I love a good Knives Out mystery. This one had a lot of socio-religious undertones which I also appreciated.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://letterboxd.com/film/yes-god-yes-2019/&quot;&gt;Yes, God, Yes&lt;/a&gt; - A movie about religion… and masturbation.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://letterboxd.com/film/teenage-mutant-ninja-turtles-mutant-mayhem/&quot;&gt;Teenage Mutant Ninja Turtles: Mutant Mayhem&lt;/a&gt; - I missed this in theaters and my kids don’t watch TMNT, but I enjoyed it. The best Turtles to-date IMHO.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Podcasts&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://open.spotify.com/show/5qXmICcFnLAqBJgMla5lsO&quot;&gt;Systems of Harm&lt;/a&gt; (S2) - I’m late to it but been enjoying season two of Systems of Harm.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://open.spotify.com/show/0uEe8tfzHciU3soYBs6ssU&quot;&gt;Nice Try&lt;/a&gt; (S1) - A podcast about failed utopias.&lt;/li&gt;
&lt;li&gt;Beyond that the usual If Books Could Kill &amp;amp; Maintenance Phase routine.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;YouTubes&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Been really into Rust vods.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;🎙 &lt;strong&gt;Recording&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Chris and I wrapped up our 14th season of Shop Talk. 695 episodes of showing up every week. Can’t believe we’ll be at 700 soon.&lt;/p&gt;
&lt;p&gt;&lt;podcast-feed&gt;&lt;/podcast-feed&gt;&lt;/p&gt;
&lt;script&gt;
customElements.define(&apos;podcast-feed&apos;, class extends HTMLElement {
  #items = [{ link: &apos;https://daverupert.com&apos;, title: { rendered: &apos;Hello world&apos; }}];

  constructor() {
    super();
    this.renderItems();
  }

  get items() {
    return this.#items
  }

  set items(data) {
    this.#items = data;
    this.renderItems();
  }

  renderItems() {
    if(!this.#items) return;

    const tmpl = `
      &lt;ul&gt;
        ${this.#items.map((item) =&gt; {
          return  `&lt;li&gt;&lt;a href=&quot;${ item.link }&quot;&gt;${item.title.rendered}&lt;/a&gt;&lt;/li&gt;`
        }).join(&apos;&apos;)}
      &lt;/ul&gt;
    `
    this.innerHTML = tmpl;
  }
})

const feedUrl = &apos;https://shoptalkshow.com/wp-json/wp/v2/posts?_fields=title,link,date&amp;before=2025-12-22T03:00:00&amp;after=2025-10-23T02:49:00&apos;;

fetch(feedUrl)
  .then(res =&gt; res.json())
  .then(json =&gt; 
    document.querySelector(&apos;podcast-feed&apos;).items = json
  ).catch(err =&gt; console.log(err))
&lt;/script&gt;
&lt;h3&gt;⌨️ &lt;strong&gt;Open source&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;🎉 &lt;a href=&quot;https://storybooks.fluentui.dev/web-components/&quot;&gt;Fluent Web Components v3&lt;/a&gt; is in Release Candidate - It’s been a lot of work (138 beta versions) to get here. But we’re happy with the progress as well as the capabilities.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;👾 &lt;strong&gt;Video games&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Retro gaming: As said above, I got into retro-gaming. I’m happy to mine this vein for awhile.&lt;/li&gt;
&lt;li&gt;Puzzle games (see blog).&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Mon, 22 Dec 2025 03:00:00 +0000</pubDate>
        <link>https://daverupert.com/2025/12/vibe-check-41/</link>
        <guid isPermaLink="true">https://daverupert.com/2025/12/vibe-check-41/</guid>
      </item>
    
      <item>
        <title>One thing churches do well</title>
        <description>&lt;p&gt;Two friends of mine (brothers, actually) got laid off from their job at a megachurch here in Austin. We met through a mutual friend that started attending their church. Our kids hang out on Roblox, so we’re connected through dadship and games. They oversaw a lot of the music and arts work that went into the weekly service. I wasn’t involved in the church so their unceremonious departure doesn’t impact me as much as folks in their community, but friends losing work is not fun and I feel for their families.&lt;/p&gt;
&lt;p&gt;[Smash cut: my son on stage playing in front of pretend groupies]&lt;/p&gt;
&lt;p&gt;My son is learning to play the guitar at School of Rock. One cool aspect about the School of Rock program is that you go from knowing nothing to performing a rock show in ~4 months after signing up. Recitals are nothing new when learning an instrument or a performing art, but those in my experience tend to be on longer annual timescales. School of Rock throws you in the deep end and that rock show commitment adds a lot of positive pressure to learn your instrument.&lt;/p&gt;
&lt;p&gt;[Smash cut: me journaling in a coffee shop in my twenties]&lt;/p&gt;
&lt;p&gt;These coinciding events got me thinking about church, music, and the relationship there of improving your craft through regular opportunities to perform. I thought about my past, my friends’ pasts, and my son’s potential future and I realized something that one thing faith-based communities do well is that they offer an endless series of opportunities for people to improve and show-off their talents.&lt;/p&gt;
&lt;p&gt;At the heart of that is a not-so-secret ladder system. Nearly every faith community I’ve been apart of has had a buffet of special interest groups to rope newcomers in and get them involved at a level that matches their skill. They ask you about your interests and then encourage you&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn1&quot; id=&quot;fnref1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; to use those in service of the community.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Play music? You can play for a small group. Prove yourself and move onto the Wednesday service. Ready for the big Sunday show? Start as the fifth guitar. Then the third. Then lead.&lt;/li&gt;
&lt;li&gt;Artistic? You do art with kids in Sunday school. Move on to making artsy b-roll videos. Your art in front of everyone in the big church: a painting, a solo, a poem, an interpretive dance!&lt;/li&gt;
&lt;li&gt;Make websites or graphics? You can manage the WordPress, make the PowerPoints legible, make the weekly pamphlets, improve the signage, and spruce up the walls.&lt;/li&gt;
&lt;li&gt;Like to talk in front of people? Go to a small group. Lead a small group. Lead a mission trip. Get on stage during the Sunday service. Lead the Sunday service when the pastor is out.&lt;/li&gt;
&lt;li&gt;Have a knack for organizing people? Join a special interest group and invite friends. Encourage people to volunteer for the local Habitat for Humanity outreach. Be the greeter who connects people to special interest groups.&lt;/li&gt;
&lt;li&gt;A closeted queer kid that loves theater? There’s the big Christmas show –sometimes with live animals!– that happens every year. Churches and youth groups love skits (for some weird reason). And the technical queers can run the soundboard or manage the lights. You may even get a headset.&lt;/li&gt;
&lt;li&gt;Know a lot about a particular topic (bible, finance, history)? Lead a Sunday school class about it. Host a weekend seminar. A whole week seminar.&lt;/li&gt;
&lt;li&gt;Handy? Join the church cleanup. Volunteer to fix that leaking window. Fix the broken A/C. Organize a shed or barn raising. Run the Habitat for Humanity group. Be the knowledgeable one on the mission trip.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There’s no shortage of jobs in a thriving community. And while some jobs skew business (the treasurer), administrative (the secretary), or mechanical (the maintenance crew); the bulk of jobs fall under the umbrella of the performing and visual arts. I find this curious in a world where getting a degree in fine arts is often chided or joked about as being non-contributing.&lt;/p&gt;
&lt;p&gt;I assume other religions across the world have different flavors of these ladders of opportunity. And I assume secular volunteer organizations might have these kinds of ladders, but I imagine they have way less acoustic guitars. The “speaker circuit” in tech sort of functions like this; local meetup, to regional conference, to national, to international, to keynote speaker, to giving a TED Talk ladder is familiar.&lt;/p&gt;
&lt;p&gt;Why would a church provide this service? What is this platform for the performing and visual arts worth? Well I can tell you we pay ~$400/month for School of Rock, so it’s somewhere in that ballpark. It’s possible this social apparatus does return dividends in the offering plate, but I think the key benefit this provides is a place of belonging. A place to exercise talents publicly and regularly that might otherwise remain dormant. Creating that ladder of opportunity is effective at keeping “involvement” –a community’s most important metric by which it lives and dies– at an all time high and engagement keeps the machine turning.&lt;/p&gt;
&lt;p&gt;[Smash cut: an announcement board with a hand-drawn thermometer that’s half-filled and renderings of a new building mounted with poster putty]&lt;/p&gt;
&lt;p&gt;In most of my experiences at a certain point (when money exchanges hands) and at a certain scale (over ~150 people), the church ladder begins to posture itself towards being another capitalistic corporate ladder with patriarchal undertones. The eternal growth model and the innate desire to build ever larger buildings replace vision and connection. The work becomes about managing real estate and optimizing to keep the pews full. Efficiency rises, the arts and music morph into a Live, Laugh, Love poster with mass appeal.&lt;/p&gt;
&lt;p&gt;Anyways, if you were trying to build a new community (or replace religion with something more compassionate)… I would think about building these kinds of ladders. I have no doubt you’ve encountered someone who has developed their gifts or skills in an incubator like this. You may even be reading a person-like-that’s blog right now.&lt;/p&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot;&gt;
&lt;p&gt;“Encourage you”, or “extract from you”, depending on your perspective or experience &lt;a href=&quot;#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
        <pubDate>Sat, 29 Nov 2025 18:36:00 +0000</pubDate>
        <link>https://daverupert.com/2025/11/communions-and-ladders/</link>
        <guid isPermaLink="true">https://daverupert.com/2025/11/communions-and-ladders/</guid>
      </item>
    
      <item>
        <title>Grid Paper</title>
        <description>&lt;script src=&quot;https://esm.sh/@zachleat/browser-window@1.0.12&quot; type=&quot;module&quot;&gt;&lt;/script&gt;
&lt;browser-window flush url=&quot;https://grid-paper.daverupert.com&quot;&gt;
&lt;img src=&quot;https://cdn.daverupert.com/posts/2025/grid-paper.jpg&quot; alt=&quot;screenshot of my grid paper app with some configurable settings in a header and a grid covering the entire background&quot; height=&quot;600&quot; width=&quot;1200&quot;&gt;
&lt;/browser-window&gt;
&lt;p&gt;&lt;a href=&quot;https://grid-paper.daverupert.com&quot; class=&quot;button&quot;&gt;Try Grid Paper&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I’ve been getting into &lt;a href=&quot;https://daverupert.com/2025/11/random-mini-dungeons/&quot;&gt;drawing dungeons on isomorphic grids&lt;/a&gt;. It’s fun but I was a little frustrated with the process of sourcing and printing out graph paper with an isomorphic grid on it. You have two bad options, basically:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Download a low-res JPG you found on Google Image search where the grid sizes are wonky and it has a giant URL on it. &lt;strong&gt;I needed something clean and simple.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Buy grid paper on Amazon in bulk. Now I’m thinking about centimeters vs. inches, cost, color, paper size, style, and quantity before I draw a single dungeon. &lt;strong&gt;I needed something ad hoc and with less commitment.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;After 15 minutes of getting frustrated I said “I can build this.” And so I did using HTML, CSS, and the tiniest bit of JavaScript. And because it’s a webpage… why limit myself to one kind of grid? I’m able to support ~7 grids types using different kinds of background gradients:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Grids&lt;/li&gt;
&lt;li&gt;Dot Grids&lt;/li&gt;
&lt;li&gt;Isomorphic Grids&lt;/li&gt;
&lt;li&gt;Isomorphic Dot Grids&lt;/li&gt;
&lt;li&gt;Dual Hex Grids&lt;/li&gt;
&lt;li&gt;Perspective Grids&lt;/li&gt;
&lt;li&gt;Two-Point Perspective Grids&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Feeling good about this little tool. The quality can be a bit blurry but background gradients and printers are weird. It’d be nice to make it crisper and I might put some effort at the task (use SVG patterns?)… but at less than 5kb and a couple of nights worth of work, I’m happy with the result. It “made the rounds” as they say on the socials and seems to be a common issue other people experience, so I’ll call that a success.&lt;/p&gt;
</description>
        <pubDate>Sun, 23 Nov 2025 18:20:00 +0000</pubDate>
        <link>https://daverupert.com/2025/11/grid-paper/</link>
        <guid isPermaLink="true">https://daverupert.com/2025/11/grid-paper/</guid>
      </item>
    
      <item>
        <title>Inkwell Games</title>
        <description>&lt;img src=&quot;https://cdn.daverupert.com/posts/2025/inkwell.jpg&quot; alt=&quot;the cute and adorable launch buttons for Inkwell Games&apos; games Stars and Fields&quot; width=&quot;1200&quot; height=&quot;630&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://inkwellgames.com/&quot;&gt;Inkwell Games&lt;/a&gt; bills itself as “Daily puzzles worth thinking about” and that’s a great tagline. Right now they offer two daily puzzles: &lt;a href=&quot;https://inkwellgames.com/games/stars&quot;&gt;Stars&lt;/a&gt; and &lt;a href=&quot;https://inkwellgames.com/games/fields&quot;&gt;Fields&lt;/a&gt;. Both are enjoyable but I rank Stars as a bit above Fields but as I get better at understanding the patterns of Fields it’s growing on me each day.&lt;/p&gt;
&lt;p&gt;Like the NYT, the puzzles grow in difficulty over the week and don’t feel bad if you miss a day because they’ll let you play any of other the puzzles from that week. I highly recommend Stars as a starter, it’s like Minesweeper meets Sudoku where each row, column, and box has two stars. It seems impossible at first, but over time you get a rhythm for cracking this cryptic.&lt;/p&gt;
&lt;p&gt;One feature both Stars and Fields have that might be controversial to puzzle purists is a “Check” button. In practice this acts sort of like a “Guess” button where you’re at a dead end and have a guess, but don’t know for sure. It happens a lot in Fields where you’re staring at a grid of numbers with no clear move. Inkwell even wrote &lt;a href=&quot;https://blog.inkwellgames.com/posts/is-looking-ahead-the-same-as-guessing-spoiler-its-not&quot;&gt;a blog post trying to de-stigmatize looking ahead&lt;/a&gt; which I appreciate immensely. The purist part of your brain feels guilty guessing at first, but in some ways it teaches you to trust your gut and intuition over time. I used to always need guesses in Stars and Fields but I’ve finished dozens on both now with zero guesses. That’s improvement and the wrinkles in my brain tingle with progress.&lt;/p&gt;
&lt;p&gt;If you’re a fan of daily puzzle games, put these in your routine. The playful aesthetic of Inkwell Games’ games always bring a smile. I’m excited to try their upcoming puzzle Snakes and roll it into my daily routine.&lt;/p&gt;
</description>
        <pubDate>Fri, 14 Nov 2025 16:14:00 +0000</pubDate>
        <link>https://daverupert.com/2025/11/inkwell-games/</link>
        <guid isPermaLink="true">https://daverupert.com/2025/11/inkwell-games/</guid>
      </item>
    
      <item>
        <title>Clues by Sam</title>
        <description>&lt;img src=&quot;https://cdn.daverupert.com/posts/2025/cluesbysam.jpg&quot; alt=&quot;A grid of emoji character tiles with names and job titles on each tile. There is one revealed tile on the edge for Pam that is green and she&apos;s saying she has 3 innocent neighbors on the edges&quot; width=&quot;1000&quot; height=&quot;798&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://cluesbysam.com/&quot;&gt;Clues By Sam&lt;/a&gt; is a daily puzzle game where you get to uncover a criminal conspiracy by following the clues… made by &lt;a href=&quot;https://games-by-sam.com/&quot;&gt;Sam&lt;/a&gt;… err… &lt;a href=&quot;https://www.hey.gg/blog/adartis&quot;&gt;Johannes&lt;/a&gt;. It’s a little if-this-then-that logic puzzle where Pam implicates Bob as a criminal and because Bob is a plumber and there’s one innocent plumber then Sally is innocent. It starts simple but overtime but often the clues will feel like they lead to a dead end… but there’s always a way to solve the puzzle. It has a sudoku-like quality to it. Like the NYT crossword the difficulty scales up over the week and is a good way to burn 10 minutes.&lt;/p&gt;
&lt;p&gt;Clues by Sam is great. It’s the first game in my daily puzzle routine. It makes me feel like the world’s greatest detective sometimes. Other times it makes me realize I’m not detail-oriented enough to be an investigator. The whole puzzle is a dopamine rush and a pang of sadness hits when I finish the puzzle for there are no more Clues By Sam left to solve that day. I think that’s a good sign of a good game; players wanting to come back. But lucky for me, Clues By Sam is now offering a puzzle pack of 50 puzzles. A nice way to hook people when they’re already addicted.&lt;/p&gt;
</description>
        <pubDate>Fri, 14 Nov 2025 15:37:00 +0000</pubDate>
        <link>https://daverupert.com/2025/11/clues-by-sam/</link>
        <guid isPermaLink="true">https://daverupert.com/2025/11/clues-by-sam/</guid>
      </item>
    
      <item>
        <title>La Rinconada, Peru</title>
        <description>&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube-nocookie.com/embed/IN1M-Xi7nk4&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;Above the clouds in the Peruvian Andes there is a town named &lt;a href=&quot;https://en.wikipedia.org/wiki/La_Rinconada,_Peru&quot;&gt;La Rinconada&lt;/a&gt;. It holds the title of being the highest year-round settlement in the world. At one point swelling to 30,000 people, the population has dwindled some now near 12,000. The weather is cold and the oxygen is thin. It’s incredible what humans are able to tolerate to survive. Existing there is dangerous, but that’s where the problems start.&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;A brief disclaimer before going further...&lt;/summary&gt;
&lt;p&gt;I want to be careful to not confuse poverty problems with systemic problems. Despite the gold in the hills, La Rinconada is a poor town. One documentary suggests people end up here because that’s the only option left for them. When talking about people in poverty, it’s easy to fall into a trap of drive-by poverty tourism and say “What a mess! Can you believe people live like this?!” but this is people’s lives and I want to be respectful of that. What I want to highlight below are the systems and power structures that create this environment.&lt;/p&gt;
&lt;/details&gt;
&lt;p&gt;La Rinconada’s entire economy centers around extracting gold from Mount Ananea. Being so far away from the nearest municipality, the unregulated mining corporations (legal and illegal) are the defacto government. Workers toil under the &lt;em&gt;cachorreo&lt;/em&gt; system, mining for 30 days straight without pay and then one day a month they get claim to as much ore as they can haul out on their person. Some prefer this deal, some get assigned to mine empty veins and make no money that month. Women –who aren’t allowed to work in the mines because of a belief they’d curse the mine– must sift and scavenge in the washes of waste rock or near the toxic cyanide and mercury contaminated tailing pools for discarded ore. It’s uncertain work in hazardous conditions. It takes around two to eight metric tons of ore to produce one ring.&lt;/p&gt;
&lt;p&gt;La Rinconada is a lawless city. A small police station exists, but they are overrun by the illegal mining corporations and the gangs. In the mines and on dark streets, murders and robberies are a common occurrence. No banks, so people carry all their cash and gold making for easy marks.  The gangs traffick humans from Peru, Bolivia, and Columbia then forced them (including minors) into prostitution. It’s generally considered not a safe place. An even harsher reality for those living there permanently.&lt;/p&gt;
&lt;p&gt;As expected with limited government services, the water in La Rinconada is not safe to drink and unmanaged waste fills the streets and alleyways. But despite all the challenges it’s still a town where people live. There is a school and there are kids playing soccer in the streets. Women sell wares in shops and offer street meats, cocoa leaves, and warm soup to hungry miners. Grass growing in concrete type of shit. A human spirit.&lt;/p&gt;
&lt;p&gt;While the struggle to survive at the top of the world is real for the people of La Rinconada, the town is for me an allegory of what life is like under a libertarian corporatocracy; where unregulated corporations profit from unfair worker wages, where women get cast to the fringes of society, and where organized crime rules the streets. If I described La Rinconada to you under the guise of a mining colony on the Moon, you’d tell me to ease off on the dystopian sci-fi shit. But this is what’s happening &lt;em&gt;on Earth&lt;/em&gt; –today– in the town closest to the Moon. It’s possible that &lt;a href=&quot;https://www.youtube.com/channel/UCEjBDKfrqQI4TgzT9YLNT8g&quot;&gt;this is what mining towns have always been like&lt;/a&gt;, but all I see is the invisible hand of unfettered Capitalism and the true cost of gilded ballroom walls.&lt;/p&gt;
</description>
        <pubDate>Thu, 13 Nov 2025 16:35:00 +0000</pubDate>
        <link>https://daverupert.com/2025/11/la-rinconada-peru/</link>
        <guid isPermaLink="true">https://daverupert.com/2025/11/la-rinconada-peru/</guid>
      </item>
    
      <item>
        <title>Golden candlesticks</title>
        <description>&lt;img src=&quot;https://cdn.daverupert.com/posts/2025/crucible.jpg&quot; alt=&quot;Cover of Arthur Miller&apos;s The Crucible&quot; height=&quot;394&quot; width=&quot;253&quot; class=&quot;book-cover&quot;&gt;
&lt;p&gt;In high school I had the weird, cyclical circumstance of reading Arthur Miller’s &lt;em&gt;The Crucible&lt;/em&gt; at least once a year at every grade level. Like Groundhog’s day but set in fictionalized 17th century Salem. While I appreciated the easy grade at the time due to uncoordinated curriculum, reading and acting out &lt;em&gt;The Crucible&lt;/em&gt; half a dozen times in those formative years means it left an imprint on my subconscious.&lt;/p&gt;
&lt;p&gt;There’s a scene in Act 2 when famous demonologist and witch hunter Reverend John Hale visits protagonist John Proctor. He’s there to shake him down about his poor church attendance and also insinuate his wife is a witch. Proctor defends himself (and his wife) and during his defense makes a big deal about the golden candlesticks in the small, clapboard church (that Proctor put the roof on). The local priest Reverend Samuel Parris –whose bewitched daughter started this whole inquisition– preached about the golden candlesticks for twenty weeks until he got them.&lt;/p&gt;
&lt;p&gt;That scene about the candlesticks always stuck out to me. It’s an embodiment of Church’s hypocrisy and materialism which Proctor detests so much that he says “it hurt my prayer.” And Proctor’s right. God doesn’t give a shit about the kind of candlesticks you use. Arguably the pewter ones made by Francis Nurse were a greater act of worship. &lt;em&gt;The Crucible&lt;/em&gt; of course is a dramatized tale, but we don’t have to look far for examples of religious figures taking material wealth from the people they’re meant to serve and to paint glamour on top of their image… then casting dispersion on the non-churchgoers and the cabal of “witches” (lebsians, probably) in the woods while your own house is not in order. It’s a morality tale about whose sin is greater.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Everyday now I watch the news and see images like this:&lt;/p&gt;
&lt;img src=&quot;https://cdn.daverupert.com/posts/2025/gilded-era.jpg&quot; alt=&quot;Donald Trump in the Oval Office meeting with a head of state. The two presidents sit in the center of the frame with the Vice President and other cabinet members forming a v-shape extening towards the camera. At the top of the frame boom microphones dangle. Behind Trump is the fireplace, now adorned in gold finishes, with gold urns on top of the mantle, and gold borers around all the picture frames (except Teddy Roosevelt). The side tables with bronze busts are also encrusted with gold. The lamps gold. The mirror gold.&quot;&gt;
&lt;p&gt;If America were some Pre-Colonial empire I might understand this image. If America was some oil-rich Arabian principality, I might understand this image. But I don’t understand this image. It looks painted on. Imported cheaply.&lt;/p&gt;
&lt;p&gt;On the walls are men who (some) through their public service earned that gold border, though they probably wouldn’t care to have it otherwise. Because they understood the job was not for them, it’s for the people. In the foreground is a selfish man who lived a life of fraud, aggrandizing himself at every opportunity, basking in the golden reflections of his fraudulence.&lt;/p&gt;
&lt;p&gt;To him this is the height of luxury and power. To me it’s an embarrassment. And in the words of John Proctor, “It hurts my prayer.”&lt;/p&gt;
</description>
        <pubDate>Thu, 13 Nov 2025 13:57:00 +0000</pubDate>
        <link>https://daverupert.com/2025/11/golden-candlesticks/</link>
        <guid isPermaLink="true">https://daverupert.com/2025/11/golden-candlesticks/</guid>
      </item>
    
      <item>
        <title>Precious Plastic</title>
        <description>&lt;p&gt;The same people behind Project Kamp also run a project called &lt;a href=&quot;https://www.preciousplastic.com/&quot;&gt;Precious Plastic&lt;/a&gt; which is an open source plastic recycling platform. As most are well aware, plastic is a major problem polluting our land, our beaches, our rivers, our oceans, and &lt;a href=&quot;https://www.npr.org/sections/health-shots/2024/05/22/1252831827/microplastics-testicles-humans-health&quot;&gt;our balls&lt;/a&gt;. While &lt;a href=&quot;https://theoceancleanup.com/&quot;&gt;Ocean Cleanup&lt;/a&gt; is progressing nicely,  &lt;a href=&quot;https://community.preciousplastic.com/news/whats-next-for-precious-plastic---v5&quot;&gt;only 10% of the world’s plastic is recycled&lt;/a&gt;. That’s appallingly low for something we know is a huge issue. That’s the problem Precious Plastic is trying to solve.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.daverupert.com/posts/2025/preciousplastic.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;How does Precious Plastic work? Like Project Kamp, they make &lt;a href=&quot;https://community.preciousplastic.com/research?sort=LatestUpdated&quot;&gt;open source research modules&lt;/a&gt; available to help you start a business recycling plastic. They offer guides on &lt;a href=&quot;https://community.preciousplastic.com/academy/build&quot;&gt;building your own machines&lt;/a&gt; , &lt;a href=&quot;https://community.preciousplastic.com/academy/create&quot;&gt;creating objects&lt;/a&gt;, &lt;a href=&quot;https://community.preciousplastic.com/academy/business&quot;&gt;running a business&lt;/a&gt;, and &lt;a href=&quot;https://community.preciousplastic.com/academy/spaces&quot;&gt;operating a space&lt;/a&gt;. There’s even a small marketplace where you can buy injection molds and a &lt;a href=&quot;https://community.preciousplastic.com/library?sort=Newest&amp;amp;category=18&quot;&gt;library of products&lt;/a&gt; for inspiration.  It’s almost like a startup in a box but instead of burning GPUs in Iowa to fancy-autocomplete some text, you’re melting garbage into table tops, cups, bowls, phone cases, and other knickknacks. Or you can specialize in making the raw materials (plastic chips, slabs, etc) that others can use to make their dream products. Nice.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.daverupert.com/posts/2025/preciousplastic.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The coolest part about Precious Plastic is that it’s a distributed open model that empowers local communities to solve their own plastic problems. My favorite example of this model is this young woman in Indonesia who recycled over 70 tons of plastic in two years while making $200k/yr.&lt;/p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube-nocookie.com/embed/phcUDITNrBE?si=TQcIQ1CoH4O-lliu&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;Inspiring. Anyways, setting up a Precious Plastic facility like this is on my tech-exit vision board short list.&lt;/p&gt;
</description>
        <pubDate>Thu, 13 Nov 2025 05:00:00 +0000</pubDate>
        <link>https://daverupert.com/2025/11/precious-plastic/</link>
        <guid isPermaLink="true">https://daverupert.com/2025/11/precious-plastic/</guid>
      </item>
    
  </channel>
</rss>

