<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Rantings of a Fellow Human</title><description>Rantings of a fellow human. Shrivas Vasudevan&apos;s notes and thoughts on life, software and design.</description><link>https://rantinghuman.com/</link><language>en-us</language><item><title>I could code that, someday</title><link>https://rantinghuman.com/notes/i-could-build-that/</link><guid isPermaLink="true">https://rantinghuman.com/notes/i-could-build-that/</guid><description>One developer&apos;s paradox of choosing DIY over buying software—and doing neither.</description><pubDate>Tue, 18 Mar 2025 22:32:00 GMT</pubDate><content:encoded>&lt;p&gt;Why would I pay for something when I could build it myself?&lt;/p&gt;
&lt;p&gt;Almost every dev has thought that at some point. Or at least, I hope they have. Otherwise I would feel like an enormous ass—for that was my attitude towards many apps I’ve come across. I’d see something cool, think to myself “Huh, I could do that”, and then proceed to forget about it.&lt;/p&gt;
&lt;p&gt;I don’t know if it also comes from having grown up in an environment where DIY was valued, over buying stuff off the shelf. Eating at home instead of eating out. Or, more likely, it’s the influence having “free” software as a child, where everything one ever used was either a demo, or shareware, or bootlegged in some way or the other. It wasn’t until my first paycheck that I actually spent it on something I otherwise would have gotten through friends of friends.&lt;/p&gt;
&lt;p&gt;It would be much later in my career when I first hear the phrase “Build vs Buy”, and get involved in those decisions at large enterprises. A turn of events that led to me actually giving this stuff some thought. After having done that for many years, I came around to the fact that, almost always, the answer to that question, is &lt;em&gt;Buy&lt;/em&gt;. In fact, that isn’t even the right question to ask, but that is a topic for another day.&lt;/p&gt;
&lt;p&gt;Why buy? As an individual, it simply comes down to one thing. Because you won’t build it. You probably could, but it ain’t happening.&lt;/p&gt;
&lt;p&gt;There could be myriad reasons as to why. Lack of time, for one. Not an interesting enough problem to solve, for another. “Don’t need it right now”. You might even start building it and realize a while later that the problem is either too hard and requires more time and sustained interest than you initially thought. Maybe the problem it solves occurs rare enough that you’re fine solving it by hand. (There are exceptions, of course—&lt;a href=&quot;https://notes.zachmanson.com/spite-driven-development/&quot; class=&quot;external-link&quot; rel=&quot;noopener&quot; target=&quot;_blank&quot;&gt;Spite-driven development&lt;/a&gt; is a thing that has worked for me in the past.)&lt;/p&gt;
&lt;p&gt;But then… LLMs come along. Time-consuming problems are suddenly less so. Everyone can just “build it themselves”, especially if their needs are straightforward enough to explain. All my dead and buried unfinished projects can be brought back to life. But, will they…?&lt;/p&gt;</content:encoded></item><item><title>Dark Mode CSS</title><link>https://rantinghuman.com/notes/dark-mode/</link><guid isPermaLink="true">https://rantinghuman.com/notes/dark-mode/</guid><description>Why do we restrict dark mode to just colors?</description><pubDate>Mon, 17 Mar 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Everyone is familiar with dark mode or night mode by now. Often times you see a website with a toggle switch (like this one). Some default to whatever the browser setting says to use. Apps on your smartphone have it. But I was wondering—why do most websites and apps settle for switching up color schemes for their dark mode?&lt;/p&gt;
&lt;p&gt;Dark meaning the absence of light, when restricted to just the set of colors one uses, gets… stale. There are only so many choices of colors one gets in dark mode while still maintaining accessibility and legibility, in content heavy websites. It’s like men’s suit pants. You’d be hard-pressed to find bold colors.&lt;/p&gt;
&lt;p&gt;Why not take things a bit further? Other things could be dark. The graphics, typography, sure. But also—personality, &lt;em&gt;intent&lt;/em&gt;. I’m thinking Dr. Jekyll and Mr. Hyde, or Tyler Durden and… the other guy. If your light mode is sunny with clear blue skies, why not make your dark mode be a dark and stormy night? Try on a whole different vibe!&lt;/p&gt;</content:encoded></item><item><title>Fun with Concentric Circles</title><link>https://rantinghuman.com/notes/fun-with-concentric-circles-css/</link><guid isPermaLink="true">https://rantinghuman.com/notes/fun-with-concentric-circles-css/</guid><description>It&apos;s not just messing around with CSS—if you document it, it&apos;s SCIENCE!</description><pubDate>Wed, 05 Mar 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;A long time ago, I was posed a series of CSS problems and exercises during an interview, the last of which sent me into a bit of a panic. Interviews are anxiety-inducing by themselves, but I was running out of time and it dawned on me how little practice I had with hand-coding CSS without looking up MDN or using frameworks.&lt;/p&gt;
&lt;p&gt;The exercise: Draw a set of 3 multi-color concentric circles.&lt;/p&gt;
&lt;p&gt;Straightforward, right? Well, I fumbled big time. After moping around a bit and having calmed down, I tried again and found a simple solution. But the wretched exercise never left my head. Over the years, I’d learn nifty CSS features, and think “here’s another way I could have done it”. So here’s my attempt to get it all out and over with.&lt;/p&gt;
&lt;h2 id=&quot;first-pass&quot;&gt;First pass&lt;/h2&gt;
&lt;p&gt;Let’s start with how a naive me did it. A series of nested &lt;code&gt;div&lt;/code&gt; tags with &lt;code&gt;relative&lt;/code&gt; positioning. Flexbox wasn’t yet widely supported back then, so it was all about &lt;code&gt;position&lt;/code&gt;. The slightly tricky part was getting the top/left positions and the sizes of the circles right so that they appear concentric and not just nested along the top-left edge (thanks, box model).&lt;/p&gt;
&lt;div class=&quot;code-demo&quot;&gt;&lt;div class=&quot;code-block&quot;&gt;&lt;pre&gt;&lt;code&gt;&amp;#x3C;div class=&quot;container&quot;&gt;
  &amp;#x3C;div class=&quot;circle outer&quot;&gt;
      &amp;#x3C;div class=&quot;circle middle&quot;&gt;
          &amp;#x3C;div class=&quot;circle inner&quot;&gt;
          &amp;#x3C;/div&gt;
      &amp;#x3C;/div&gt;
  &amp;#x3C;/div&gt;
&amp;#x3C;/div&gt;

&amp;#x3C;style&gt;
  .circle {
      border-radius: 50%;
      position: relative;
  }

  .outer {
      width: 12rem;
      height: 12rem;
      background: tomato;
  }

  .middle {
      width: 10rem;
      height: 10rem;
      background: palegreen;
      top: 1rem;
      left: 1rem;
  }

  .inner {
      width: 8rem;
      height: 8rem;
      background: lightskyblue;
      top: 1rem;
      left: 1rem;
  }

  body {
      margin: 0;
      padding: 0;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      min-height: 100vh;
  }
  .container {
      outline: 2px dashed rgba(0, 0, 0, 0.5);
  }

  .circle {
      opacity: 0;
      animation-duration: 8s;
      animation-iteration-count: infinite;
  }

  .outer {
      animation-name: outer;

  }

  .middle {
      animation-name: middle;
  }

  .inner {
      animation-name: inner;
  }

  @keyframes outer {

      0%,
      100% {
          opacity: 0;
      }

      10%,
      70% {
          opacity: 1;
      }

      85%,
      95% {
          opacity: 0;
      }
  }

  @keyframes middle {

      0%,
      20%,
      100% {
          opacity: 0;
      }

      30%,
      70% {
          opacity: 1;
      }

      85%,
      95% {
          opacity: 0;
      }
  }

  @keyframes inner {

      0%,
      40%,
      100% {
          opacity: 0;
      }

      50%,
      70% {
          opacity: 1;
      }

      85%,
      95% {
          opacity: 0;
      }
  }
&amp;#x3C;/style&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href=&quot;https://rantinghuman.com/notes/fun-with-concentric-circles-css/&quot;&gt;See the live demo on the site →&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;There is a direct relationship between the left/top offsets and the circle widths, expressed by this formula:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Width of inner circle = Width of outer circle - 2 * offset&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So, if your outer circle was &lt;code&gt;100px&lt;/code&gt;, and your inner circle &lt;code&gt;80px&lt;/code&gt;, you’d have to make sure the top and left offsets were &lt;code&gt;10px&lt;/code&gt;.
The formula works because the offset centers the inner circle by dividing the total size difference evenly on all sides. Applying half of the size difference as the offset keeps the inner circle perfectly aligned within the outer circle.&lt;/p&gt;
&lt;p&gt;Cool, so that’s one way to do it. But, what if you didn’t want a mess of nested HTML tags in your code that could potentially be difficult to read?&lt;/p&gt;
&lt;h2 id=&quot;enter-pseudo-elements&quot;&gt;Enter pseudo-elements&lt;/h2&gt;
&lt;p&gt;With &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/::before&quot; class=&quot;external-link&quot; rel=&quot;noopener&quot; target=&quot;_blank&quot;&gt;&lt;code&gt;::before&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/::after&quot; class=&quot;external-link&quot; rel=&quot;noopener&quot; target=&quot;_blank&quot;&gt;&lt;code&gt;::after&lt;/code&gt;&lt;/a&gt;, you could use fewer &lt;code&gt;div&lt;/code&gt;s to accomplish the same thing, in almost the same way. A few things to note here:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;These are not nested one within the other—they’re at the same level. Which means you’d have to add &lt;code&gt;absolute&lt;/code&gt; positioning to the pseudo-elements to make them stay concentric. This also messes with your offsets a bit—both inner circles need to be positioned relative to the base element.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;::before&lt;/code&gt; comes, well, &lt;em&gt;before&lt;/em&gt; &lt;code&gt;::after&lt;/code&gt;, but not before the element itself in the stacking order—it comes before the &lt;em&gt;content&lt;/em&gt; of your element. Both are children of your base element.  While it may seem like &lt;code&gt;::before&lt;/code&gt; ought to be the outermost / bottom circle, your base element actually fills that role (barring any &lt;code&gt;z-index&lt;/code&gt; shenanigans).&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;div&amp;gt;
    ::before
    ::after
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;code-demo&quot;&gt;&lt;div class=&quot;code-block&quot;&gt;&lt;pre&gt;&lt;code&gt;&amp;#x3C;div class=&quot;container&quot;&gt;
  &amp;#x3C;div class=&quot;pseudo-circle&quot;&gt;
  &amp;#x3C;/div&gt;
&amp;#x3C;/div&gt;
&amp;#x3C;style&gt;
  .pseudo-circle {
      width: 12rem;
      height: 12rem;
      border-radius: 50%;
      background: tomato;
      position: relative;
  }

  .pseudo-circle::before {
      content: &apos;&apos;;
      width: 10rem;
      height: 10rem;
      border-radius: 50%;
      background: palegreen;
      position: absolute;
      top: 1rem;
      left: 1rem;
  }

  .pseudo-circle::after {
      content: &apos;&apos;;
      width: 8rem;
      height: 8rem;
      border-radius: 50%;
      background: lightskyblue;
      position: absolute;
      top: 2rem;
      left: 2rem;
  }

  body {
      margin: 0;
      padding: 0;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      min-height: 100vh;
  }
  .container {
      outline: 2px dashed rgba(0, 0, 0, 0.5);
  }

  .pseudo-circle,
  .pseudo-circle::before,
  .pseudo-circle::after {
      opacity: 0;
      animation-duration: 8s;
      animation-iteration-count: infinite;
  }

  .pseudo-circle {
      animation-name: outer;
  }

  .pseudo-circle::before {
      animation-name: middle;
  }

  .pseudo-circle::after {
      animation-name: inner;
  }

  @keyframes outer {

      0%,
      100% {
          opacity: 0;
      }

      10%,
      70% {
          opacity: 1;
      }

      85%,
      95% {
          opacity: 0;
      }
  }

  @keyframes middle {

      0%,
      20%,
      100% {
          opacity: 0;
      }

      30%,
      70% {
          opacity: 1;
      }

      85%,
      95% {
          opacity: 0;
      }
  }

  @keyframes inner {

      0%,
      40%,
      100% {
          opacity: 0;
      }

      50%,
      70% {
          opacity: 1;
      }

      85%,
      95% {
          opacity: 0;
      }
  }
&amp;#x3C;/style&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href=&quot;https://rantinghuman.com/notes/fun-with-concentric-circles-css/&quot;&gt;See the live demo on the site →&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;This results in more or less the same number of DOM elements in the end. And, you are kind of limited to 3 concentric circles per element this way. Unless…&lt;/p&gt;
&lt;h2 id=&quot;box-shadows&quot;&gt;Box Shadows&lt;/h2&gt;
&lt;p&gt;While &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/box-shadow&quot; class=&quot;external-link&quot; rel=&quot;noopener&quot; target=&quot;_blank&quot;&gt;box shadows&lt;/a&gt; are generally used to, well, cast shadows, they can also be used to make copies of your element, at various sizes! For our needs, we ignore the length values for x and y offsets and the blur radius, and focus on the spread radius (the fourth length value).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;box-shadow: 0 0 0 10px red;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What’s that? That’s just one circle, you say? You can layer more box-shadows! Just keep increasing the spread for bigger and bigger circles.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;box-shadow: 0 0 0 10px red, 0 0 0 20px blue, 0 0 0 30px green;&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;code-demo&quot;&gt;&lt;div class=&quot;code-block&quot;&gt;&lt;pre&gt;&lt;code&gt;&amp;#x3C;div class=&quot;container&quot;&gt;
  &amp;#x3C;div class=&quot;shadow-circle&quot;&gt;
  &amp;#x3C;/div&gt;
&amp;#x3C;/div&gt;

&amp;#x3C;style&gt;
  .shadow-circle {
      width: 8rem;
      height: 8rem;
      border-radius: 50%;
      background: lightskyblue;
      opacity: 0;
      box-shadow: 0 0 0 1rem palegreen,
          0 0 0 2rem tomato;
      animation: shadow 8s infinite;
  }

  body {
      margin: 0;
      padding: 0;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      min-height: 100vh;
  }
  .container {
      outline: 2px dashed rgba(0, 0, 0, 0.5);
  }
  html {
      margin: 0;
      padding: 0;
  }

  @keyframes shadow {

      0%,
      100% {
          box-shadow: 0 0 0 1rem rgb(152, 251, 152, 0),
              0 0 0 2rem rgb(255, 99, 71, 0);
          opacity: 0;
      }

      20%,
      70% {
          box-shadow: 0 0 0 1rem rgb(152, 251, 152, 0),
              0 0 0 2rem rgb(255, 99, 71, 0);
          opacity: 1;
      }

      40%,
      70% {
          box-shadow: 0 0 0 1rem rgb(152, 251, 152, 1),
              0 0 0 2rem rgb(255, 99, 71, 0);
          opacity: 1;
      }

      60%,
      70% {
          box-shadow: 0 0 0 1rem rgb(152, 251, 152, 1),
              0 0 0 2rem rgb(255, 99, 71, 1);
          opacity: 1;
      }

      85%,
      95% {
          box-shadow: 0 0 0 1rem rgba(152, 251, 152, 0),
              0 0 0 2rem rgba(255, 99, 71, 0);
          opacity: 0;
      }
  }
&amp;#x3C;/style&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href=&quot;https://rantinghuman.com/notes/fun-with-concentric-circles-css/&quot;&gt;See the live demo on the site →&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;Something to note here: shadows, like in the physical world, do not occupy space. You will need to think about positioning offsets if you don’t want your shadows overlapping other elements or disappearing outside the browser window. Another potential problem is that once you hit a certain number of box shadows, performance begins to suffer, with all the painting the browser has to do.&lt;/p&gt;
&lt;p&gt;One of the more annoying problems, in my view, is how certain browsers (&lt;a href=&quot;https://issues.chromium.org/issues/40838329&quot; class=&quot;external-link&quot; rel=&quot;noopener&quot; target=&quot;_blank&quot;&gt;Chrome&lt;/a&gt;) start distorting the shadows once they get past a certain size relative to your base element. The circular shadows start looking like rounded squares. This, apparently, is according to spec! &lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/7103&quot; class=&quot;external-link&quot; rel=&quot;noopener&quot; target=&quot;_blank&quot;&gt;More discussion about the relevant W3C spec here.&lt;/a&gt;&lt;/p&gt;
&lt;img src=&quot;https://rantinghuman.com/_astro/box-shadow.B-o4PlDt.png&quot; alt=&quot;Distorted box shadows in Chrome&quot;&gt;
&lt;div class=&quot;code-demo&quot;&gt;&lt;div class=&quot;code-block&quot;&gt;&lt;pre&gt;&lt;code&gt;&amp;#x3C;div class=&quot;container&quot;&gt;
  &amp;#x3C;div class=&quot;shadow-circle&quot;&gt;
  &amp;#x3C;/div&gt;
&amp;#x3C;/div&gt;
&amp;#x3C;style&gt;
  .shadow-circle {
      width: 6rem;
      position: relative;
      height: 6rem;
      border-radius: 50%;
      background: lightskyblue;
      box-shadow: 0 0 0 6rem palegreen,
          0 0 0 8rem tomato;
      animation: shadow 8s infinite;
  }

  body {
      margin: 0;
      padding: 0;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      min-height: 100vh;
  }
  .container {
      outline: 2px dashed rgba(0, 0, 0, 0.5);
  }

   @keyframes shadow {

      0%,
      100% {
          box-shadow: 0 0 0 1rem palegreen,
              0 0 0 2rem tomato;
      }

      40%,
      60% {
          box-shadow: 0 0 0 6rem palegreen,
              0 0 0 8rem tomato;
      }
  }
&amp;#x3C;/style&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href=&quot;https://rantinghuman.com/notes/fun-with-concentric-circles-css/&quot;&gt;See the live demo on the site →&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;One workaround to this is to bring in pseudo elements once again, making them close enough to the shadow size you need, and then adding box-shadow to the pseudo elements. Feels like overkill… What else can we do?&lt;/p&gt;
&lt;h2 id=&quot;radial-gradients-to-the-rescue&quot;&gt;Radial Gradients to the rescue&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/radial-gradient&quot; class=&quot;external-link&quot; rel=&quot;noopener&quot; target=&quot;_blank&quot;&gt;Radial gradients&lt;/a&gt; are so cool. I see this approach as kind of the inverse of the box shadow approach—instead of starting with the innermost circle and adding shadows that expand outward (although, there are inner box shadows too), you start with one circle and add gradients that make it seem like there are more circles within. You need to be mindful of the color stops in your gradient setup so that there’s no blending involved—just hard stops from one circle’s edge to the next.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;background: radial-gradient(circle at center, blue 50px, red 50px)&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;code-demo&quot;&gt;&lt;div class=&quot;code-block&quot;&gt;&lt;pre&gt;&lt;code&gt;&amp;#x3C;div class=&quot;container&quot;&gt;
  &amp;#x3C;div class=&quot;gradient-circle&quot;&gt;&amp;#x3C;/div&gt;
&amp;#x3C;/div&gt;
&amp;#x3C;style&gt;
  .gradient-circle {
      width: 12rem;
      height: 12rem;
      border-radius: 50%;
      background: radial-gradient(
          circle at center,
          lightskyblue 4rem,
          palegreen 4rem,
          palegreen 5rem,
          tomato 5rem);
      position: relative;
  }

  body {
      margin: 0;
      padding: 0;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      min-height: 100vh;
  }
  .container {
      outline: 2px dashed rgba(0, 0, 0, 0.5);
  }
&amp;#x3C;/style&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href=&quot;https://rantinghuman.com/notes/fun-with-concentric-circles-css/&quot;&gt;See the live demo on the site →&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;And just like box shadows, you can layer multiple radial gradients, with the added bonus of not having to worry about overlapping other elements or the distortion problem.&lt;/p&gt;
&lt;h2 id=&quot;some-things-to-consider&quot;&gt;Some things to consider&lt;/h2&gt;
&lt;p&gt;Why would you pick one of these approaches over the other? Maybe you want to animate one or more circles independent of the rest. While &lt;code&gt;transform&lt;/code&gt; can animate individual DOM elements buttery smooth with interpolation, animating certain types of changing backgrounds is not as fluid, causing stutters.&lt;/p&gt;
&lt;div class=&quot;code-demo&quot;&gt;&lt;div class=&quot;code-block&quot;&gt;&lt;pre&gt;&lt;code&gt;&amp;#x3C;div class=&quot;container&quot;&gt;
  &amp;#x3C;div class=&quot;circle outer tone rotate&quot;&gt;
      &amp;#x3C;div class=&quot;circle middle tone rotate&quot;&gt;
          &amp;#x3C;div class=&quot;circle inner tone rotate&quot;&gt;
          &amp;#x3C;/div&gt;
      &amp;#x3C;/div&gt;
  &amp;#x3C;/div&gt;
&amp;#x3C;/div&gt;
&amp;#x3C;div class=&quot;container&quot;&gt;
  &amp;#x3C;div class=&quot;circle outer&quot;&gt;
      &amp;#x3C;div class=&quot;circle middle&quot;&gt;
          &amp;#x3C;div class=&quot;circle inner pulse&quot;&gt;
          &amp;#x3C;/div&gt;
      &amp;#x3C;/div&gt;
  &amp;#x3C;/div&gt;
&amp;#x3C;/div&gt;
&amp;#x3C;div class=&quot;container&quot;&gt;
  &amp;#x3C;div class=&quot;gradient-circle pulse-gradient&quot;&gt;
  &amp;#x3C;/div&gt;
&amp;#x3C;/div&gt;
&amp;#x3C;style&gt;
  .circle {
      border-radius: 50%;
      position: relative;
      display: flex;
      justify-content: center;
      align-items: center;
  }

  .outer {
      width: 12rem;
      height: 12rem;
      background: tomato;
      &amp;#x26;.tone {
          background: linear-gradient(90deg,
                  tomato 50%,
                  #ff9980 50%);
      }
  }

  .middle {
      width: 10rem;
      height: 10rem;
      background: palegreen;
      &amp;#x26;.tone {
          background: linear-gradient(90deg,
                  palegreen 50%,
                  #c1ffc1 50%);
      }
  }

  .inner {
      width: 8rem;
      height: 8rem;
      background: lightskyblue;
      &amp;#x26;.tone {
          background: linear-gradient(90deg,
                  lightskyblue 50%,
                  #b0e2ff 50%);
      }
  }

  .gradient-circle {
      width: 12rem;
      height: 12rem;
      border-radius: 50%;
      background: radial-gradient(
              circle at center,
              lightskyblue 4rem,
              palegreen 4rem,
              palegreen 5rem,
              tomato 5rem);
      position: relative;
  }

  .rotate {
      animation: rotate-clockwise
      8s linear infinite;
  }

  .rotate:odd {
      animation: rotate-counterclockwise
       8s linear infinite;
  }

  .pulse {
      animation: pulse 2s infinite;
  }

  .pulse-gradient {
      animation: pulse-gradient 2s infinite;
  }

  @keyframes rotate-clockwise {
      from {
          transform: rotate(0deg);
      }

      to {
          transform: rotate(360deg);
      }
  }

  @keyframes rotate-counterclockwise {
      from {
          transform: rotate(0deg);
      }

      to {
          transform: rotate(-360deg);
      }
  }

  @keyframes pulse {
      0% {
          transform: scale(0.95);
      }

      50% {
          transform: scale(1.1);
      }

      100% {
          transform: scale(0.95);
      }
  }

  @keyframes pulse-gradient {
      0% {
          background: radial-gradient(
                  circle at center,
                  lightskyblue 4rem,
                  palegreen 4rem,
                  palegreen 5rem,
                  tomato 5rem);
      }

      50% {
          background: radial-gradient(
                  circle at center,
                  lightskyblue 4.5rem,
                  palegreen 4rem,
                  palegreen 5rem,
                  tomato 5rem);
      }

      100% {
          background: radial-gradient(
                  circle at center,
                  lightskyblue 4rem,
                  palegreen 4rem,
                  palegreen 5rem,
                  tomato 5rem);
      }
  }

  body {
      margin: 0;
      padding: 0;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      min-height: 100vh;
      gap: 0.5rem;
  }
&amp;#x3C;/style&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href=&quot;https://rantinghuman.com/notes/fun-with-concentric-circles-css/&quot;&gt;See the live demo on the site →&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;Keen-eyed readers might have noticed that I didn’t animate the earlier radial gradient example, for this exact reason. Using &lt;code&gt;radial-gradient()&lt;/code&gt; results in an object of the &lt;code&gt;gradient&lt;/code&gt; data type, which is a special kind of image. So in effect, we are using the &lt;code&gt;background-image&lt;/code&gt; property, which, while animatable, will be annoying to make smooth—there is no interpolation between color stops. It just switches from one to the next. Great if you like stop-motion animation!&lt;/p&gt;
&lt;p&gt;You could code up 24, or 60, or even 144 steps of &lt;code&gt;@keyframes&lt;/code&gt; to try to make it smooth, but you’re going to have inconsistencies across displays depending on refresh rates. And who wants to write all that up anyway! (AI, probably).&lt;/p&gt;
&lt;p&gt;You might also want to add more styles to each circle, such as a border. That would complicate the circle math in the nested &lt;code&gt;div&lt;/code&gt; example but not by much. Both box shadows and radial gradients make it easy - you just add more layers / color stops.&lt;/p&gt;
&lt;h2 id=&quot;other-ways&quot;&gt;Other ways&lt;/h2&gt;
&lt;p&gt;There are many more ways to do this, including using CSS Grid, SVGs, the Canvas API, perhaps even getting fancy with &lt;code&gt;clip-path&lt;/code&gt; and &lt;code&gt;mask-image&lt;/code&gt; and the like. I’ve yet to explore each of them enough to write about. Perhaps one day, if I’m still thinking about that damn interview question.&lt;/p&gt;</content:encoded></item><item><title>We are all Taravangian</title><link>https://rantinghuman.com/notes/we-are-all-taravangian/</link><guid isPermaLink="true">https://rantinghuman.com/notes/we-are-all-taravangian/</guid><description>Why I keep attempting to write for myself, time and again.</description><pubDate>Mon, 24 Feb 2025 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Minor spoilers ahead if you haven’t yet but intend to read books in &lt;a href=&quot;https://www.brandonsanderson.com/pages/the-stormlight-archive-series&quot; class=&quot;external-link&quot; rel=&quot;noopener&quot; target=&quot;_blank&quot;&gt;The Stormlight Archive&lt;/a&gt; by Brandon Sanderson. This one is likely not going to age well given the state of Taravangian as of Books 4 and 5.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Taravangian is one of the many great characters in the Stormlight Archive. A king who wants to do right by his people, at least according to him. At some point before the events of the series, he asks for a boon from a… erm… deity of sorts, to give him the capacity to save humankind. This boon is granted, in the form of great intelligence and great compassion—but he is also cursed to never have them at the same time. You see, this deity had some ulterior motives that were not immediately obvious, somewhat like trickster gods from mythology.&lt;/p&gt;
&lt;p&gt;As a result, Taravangian is very intelligent on certain days (and almost a sociopath, but let’s ignore that for now), and somewhat lacking in intellect (but very compassionate) on others. His intelligence and compassion levels fluctuate day to day, inversely proportional to each other, with extreme days of either being relatively rare. He attempts to cope with this multiple ways—taking daily tests to check his mental state, having systems in place to stop him from making decisions when he’s having an unintelligent day, and so on.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Chart showing Taravangian&amp;#39;s intelligence and compassion fluctuate inversely proportional to each other over time&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2091&quot; height=&quot;1416&quot; src=&quot;https://rantinghuman.com/_astro/taravangian-chart.C0DLwvm3_ZG5Sez.webp&quot;&gt;&lt;/p&gt;
&lt;p&gt;But, the thing I’m interested in, is this: On a day of peak intelligence, he spends his time writing extensive instructions, codes, predictions, and plans across every surface of his bedroom, including inventing hieroglyphics. All of this is later compiled into an epic text called “The Diagram”, which serves as a complex and often cryptic guide for both Taravangian himself and his followers in their efforts to “save humanity”.&lt;/p&gt;
&lt;p&gt;It recently struck me that I too can be like Taravangian, feeling like a genius on some days, but really thickheaded on others. At the very least, we all have had good days and bad days. But unlike this blessed king, I didn’t always write stuff down on my best days. I relied almost entirely on my memory for most of my life.&lt;/p&gt;
&lt;p&gt;I kept getting told my memory was like a “steel trap” because I could often remember past events or decisions and the reasons behind them. If I couldn’t remember them word for word, I’d at least remember where or how to find the relevant documentation. This often involved combing through emails, chat histories, browser histories, etc. for context or links to documents. I had developed an unwritten standard operating procedure for recall, clunky as it was. The habit of taking notes for myself was never something I kept up, because I thought I could remember everything. And I did not see that there was a problem with that.&lt;/p&gt;
&lt;p&gt;A couple of years into my career, I started writing again after I saw my boss taking meeting notes in Evernote (I’m easily influenced, turns out). I would end up going down several rabbit holes of writing apps over the years (as I’m sure many have), and keep pen and paper journals as well. I’m coming to believe that writing is &lt;em&gt;essential&lt;/em&gt; to connect the two Taravangian states of self. I find myself needing to refer to the notes I wrote on my “good” days to get me through my “bad” days. This is becoming increasingly obvious to me in a way that it did not before, as I grow older and find my memory letting me down on more often than I would like. Although, there are times when I wonder if it was after I started keeping a journal that my memory started to falter, because sometimes, &lt;a href=&quot;https://www.reproof.app/blog/notes-apps-help-us-forget&quot; class=&quot;external-link&quot; rel=&quot;noopener&quot; target=&quot;_blank&quot;&gt;you write to forget&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;More importantly—writing helps me think. Having thoughts in my head is not enough; I need to be able to externalize them somehow to understand them and evaluate them for what they are. It helps me understand myself better, and does wonders for my mental health.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“If you can’t read and write, you can’t think. Your thoughts are dispersed if you don’t know how to read and write. You’ve got to be able to look at your thoughts on paper and discover what a fool you were.”
— Ray Bradbury&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I remember that I found it very easy to spend a lot of time on “research” (also known as procrastination, in some circles) around how and where to write. I have a “productivity” folder full of bookmarks related to personal knowledge management systems. PARA! Zettelkasten! Commonplace book! Bullet journal! Johnny decimal! It took a while before the obvious hit me—it doesn’t matter. Just write. If a system makes it harder for me to get started putting words to paper or screen, it’s probably not the right one. It was certainly helpful to pick one system to start with—I used the basic bullet journal method when I wanted to go back to paper, and I still try to keep that going for journaling, as there’s something about writing slowly with a pen that feels better for diary-type stuff. Most of my daily note-taking and processing (including writing for this site) is now done using Obsidian—&lt;a href=&quot;https://www.youtube.com/watch?v=WgV6M1LyfNY&quot; class=&quot;external-link&quot; rel=&quot;noopener&quot; target=&quot;_blank&quot;&gt;because plain text rules&lt;/a&gt;. Hopefully, my notes can serve as a guide for future me, like the Diagram did for poor old (&lt;em&gt;cough&lt;/em&gt;) Taravangian.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Picture of Obsidian graph view, showing interconnected notes&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1454&quot; height=&quot;1486&quot; src=&quot;https://rantinghuman.com/_astro/obsidian-graph.Dtv636we_Z1O9KU2.webp&quot;&gt;&lt;/p&gt;</content:encoded></item></channel></rss>