<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.3.4">Jekyll</generator><link href="https://annafilou.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://annafilou.com/" rel="alternate" type="text/html" /><updated>2026-10-09T13:18:58+00:00</updated><id>https://annafilou.com/feed.xml</id><title type="html">Anna Filou</title><subtitle>Product/UI Designer based in Athens, working internationally.</subtitle><entry><title type="html">Untranslatable Greek words</title><link href="https://annafilou.com/greek-words/" rel="alternate" type="text/html" title="Untranslatable Greek words" /><published>2026-09-30T00:00:00+00:00</published><updated>2026-09-30T00:00:00+00:00</updated><id>https://annafilou.com/greek-words</id><content type="html" xml:base="https://annafilou.com/greek-words/"><![CDATA[<p>I just spent 2 hours correcting a list of supposedly untranslatable Greek words on <a href="https://eunoia.world/?words%5Bword%5D=&amp;words%5Blanguagetag%5D=Greek&amp;words%5Btag%5D=">eunoia.world</a>.</p>

<p><img src="/assets/blog/greek-words-eunoia.jpg" alt="Eunoia.world page titled Untranslatable Greek Words, listing entries such as Eunoia, Philotimo, and Philoxenia" /></p>

<p><strong>Many were in fact easily translatable</strong>, some had wrong definitions, a few were duplicates, one was Latin, and some were recently coined Greek-<strong>sounding</strong> words! I emailed the site’s owner and it’d be cool if they updated it, but this seems like an old side project, so we’ll see.</p>

<p>In any case, I didn’t want to feel like I might have completely wasted my effort, so here I am sharing the words, with the correct definitions, and my favorite wrong ones.</p>

<h2 id="context">Context</h2>

<p>Eunoia.world is an online directory of “untranslatable words”, AKA words without a direct, single-word translation in most other languages.</p>

<p>Anyone can “suggest” a word for the site’s owner to add to the list.</p>

<p><img src="/assets/blog/greek-words-suggest.jpg" alt="Eunoia form titled Suggest a new word, with fields for Name, Definition, Language, and Tags" /></p>

<p>What I found fascinating is that, apparently, some people suggested common Greek words, but with highly romanticized, fancy definitions that are simply untrue.</p>

<h2 id="the-romanticized-ordinary-words">The romanticized ordinary words</h2>

<h3 id="volta">Volta</h3>

<ul>
  <li>Greek: βόλτα</li>
  <li>Real meaning: walk, stroll. As in, “I’m going for a walk”.</li>
  <li>Eunoia “definition”: “During certain hours of the early evening, around dusk, everyone in the town who might feel like going for a walk takes a saunter or stroll up and down the main street”.</li>
</ul>

<p>Just… what? That’s not a definition! It’s a description of a behavior. Someone tried to make this standard Greek word (of Italian origin, actually) sound like a profound tradition, when it’s just a word. Some people just like to go for walks, some around dusk. It’s not deep.</p>

<h3 id="parea">Parea</h3>

<ul>
  <li>Greek: παρέα</li>
  <li>Real meaning: friend group, clique.</li>
  <li>Eunoia “definition”: “A group of friends who regularly gather together to share their experiences about life, their philosophies, values and ideas.”</li>
</ul>

<p>All of that additional stuff is completely invented out of thin air. Again, someone was trying too hard to make a standard Greek word sound much deeper than it is.</p>

<h3 id="andria">Andria</h3>

<ul>
  <li>Greek: ανδρεία</li>
  <li>Real meaning: courage.</li>
  <li>Eunoia “definition”: “Both valour and courage, expressed in actions in front of the face of danger”.</li>
</ul>

<p>Whoever wrote this was trying too hard. Incidentally, this word’s root is the Greek word for “man”. So it literally means something like “the essence of masculinity”…</p>

<h3 id="eunoia">Eunoia</h3>

<ul>
  <li>Real meaning: favor, goodwill.</li>
  <li>Website “definition”: A well-mind; beautiful thinking.</li>
</ul>

<p>Ironically, despite being the domain name of the site, Eunoia itself is translatable. It means “favor”, as in “he invited the one he favors”. It’s used in figures of speech like “to be favored by luck” (έχει την εύνοια της τύχης).</p>

<p>It <em>does</em> literally mean “good mind” (ευ + νους), but that’s not what it actually <em>means</em>. Not even in ancient Greek. “Good mind” (or “good thinking”) was meant metaphorically, as in “my thoughts towards you are good” → you have my goodwill, my favor.</p>

<h2 id="the-made-up-ones">The made-up ones</h2>

<h3 id="anemoia">Anemoia</h3>

<ul>
  <li>Eunoia “definition”: “Nostalgia for a time that you have never lived”.</li>
</ul>

<p>I was confused because I first read this as “Anemia” (lack of hemoglobin). But it’s actually not a Greek word at all. It was coined in 2012 by John Koenig for his project <em>The Dictionary of Obscure Sorrows</em>. In other words, not a real word.</p>

<h3 id="euneirophrenia">Euneirophrenia</h3>

<ul>
  <li>Eunoia “definition”: “The peace of mind that comes with having pleasant dreams.”</li>
  <li>It was also misspelled as “Eun<strong>o</strong>irophrenia”</li>
</ul>

<p>This isn’t a real Greek word. It looks like a blend of ευ (“good”) + όνειρο (“dream”) + φρήν (“mind”). Someone must have “coined” it recently, although I can’t find out who. Listicle writers (as usual) didn’t do their research and started presenting it as a real Greek word.</p>

<p>But if you search for this word on Google in Greek (“ευνειροφρένια”), there are literally 0 results — what a rare sight! It’s only in English that you get results. So much for being an untranslatable “Greek” word ;)</p>

<p><img src="/assets/blog/greek-words-google.jpg" alt="Google search for the Greek spelling of euneirophrenia, with a notice that 0 results were displayed" /></p>

<p>I suppose after this post gets indexed, there’ll be a single result. 🤔</p>

<h2 id="the-love-types">The love types</h2>

<p>In the 20th century, writers like C.S. Lewis and John Alan Lee borrowed Greek and Latin words as the names for love styles they came up with. Years later, online listicles started presenting them as ancient Greek concepts, but they’re not.</p>

<p>Understandably, some people came to believe that the meaning of those Greek and Latin words = the love type the writers described. I don’t mind the oversight because it introduced me to <a href="https://en.wikipedia.org/wiki/John_Alan_Lee">John Alan Lee</a>, who has done <a href="https://xtramagazine.com/power/proud-life-activist-and-rebel-john-alan-lee-56658">quite a few</a> <a href="https://www.cbc.ca/news/health/john-alan-lee-pushes-limits-of-canada-s-assisted-suicide-debate-1.2627093">interesting things</a> in his life.</p>

<h3 id="agape">Agape</h3>

<ul>
  <li>Greek: αγάπη</li>
  <li>Real meaning: love.</li>
  <li>Eunoia “definition”: selfless love to all, universal loving kindness</li>
</ul>

<p>Nope, it’s just “plain” love. A great concept indeed, but decidedly not untranslatable.</p>

<h3 id="philia">Philia</h3>

<ul>
  <li>Greek: φιλία</li>
  <li>Real meaning: friendship.</li>
  <li>Eunoia “definition”: “‘highest form of love’; deep love between friends, brotherly love”.</li>
</ul>

<p>This one is also just “friendship”. There’s no other word for “plain” friendship, as opposed to this supposed “deep love between friends”.</p>

<h3 id="pragma">Pragma</h3>

<ul>
  <li>Greek: πράγμα</li>
  <li>Real meaning: thing, object.</li>
  <li>Eunoia “definition”: “longtime love, such as in long marriages”.</li>
</ul>

<p>Pragma was John Lee’s nickname for “pragmatic love”.</p>

<h3 id="ludus">Ludus</h3>

<p>John Lee’s “playful love”. This one isn’t even Greek. It’s Latin.</p>

<h2 id="the-actually-untranslatable-ones">The actually untranslatable ones</h2>

<p>After this exercise, I was left with a list of actually untranslatable Greek words, which I present to you below.</p>

<ul>
  <li><strong>Akrasia</strong>
    <ul>
      <li>Greek: ακρασία</li>
      <li>Acting against your own better judgment; lack of self-control. Literally “lack of power (over yourself)” (α- “not” + κράτος “strength, power”). Inability to “hold” oneself back (κρατάω = hold). Note: I’d never encountered this word.</li>
    </ul>
  </li>
  <li><strong>Charmolypi</strong>
    <ul>
      <li>Greek: χαρμολύπη</li>
      <li>Joy mixed with sorrow; bittersweet. Literally “joy-sorrow” (χάρμα “joy” + λύπη “sorrow”). Note: I’ve never encountered this word. It’s apparently rare and literary.</li>
    </ul>
  </li>
  <li><strong>Evdaimonia</strong>
    <ul>
      <li>Greek: ευδαιμονία</li>
      <li>Intense happiness; a state of flourishing and good fortune. Literally in “good spirits” (ευ “good” + δαίμων “spirit”).</li>
    </ul>
  </li>
  <li><strong>Filotimo</strong>
    <ul>
      <li>Greek: φιλότιμο</li>
      <li>The inner impulse to act well and in line with the moral virtues of your society and upbringing. Literally “love of honor” (φίλος “dear, loving” + τιμή “honor”).</li>
    </ul>
  </li>
  <li><strong>Meraki</strong>
    <ul>
      <li>Greek: μεράκι</li>
      <li>Doing something with soul, creativity or love; putting something of yourself into it. From Turkish merak (“curiosity, keen interest”).</li>
    </ul>
  </li>
  <li><strong>Nipenthes</strong>
    <ul>
      <li>Greek: νηπενθές</li>
      <li>In the Odyssey, a fictional drug that makes you forget grief. Literally “no grief” (νη- “not” + πένθος “grief”). Note: had to look this one up. Not sure it qualifies as a real word, since it’s the name of a fictional drug.</li>
    </ul>
  </li>
  <li><strong>Polytropos</strong>
    <ul>
      <li>Greek: πολύτροπος</li>
      <li>“Of many ways”: versatile, cunning, much-wandering. Homer’s epithet for Odysseus in the first line of the Odyssey. Πολύς “many, much” + τρόπος “way”.</li>
    </ul>
  </li>
  <li><strong>Ripsaspis</strong>
    <ul>
      <li>Greek: ρίψασπις</li>
      <li>One who throws away his shield in battle; a coward or deserter. Literally “shield-thrower” (ρίπτω “throw” + ασπίς “shield”).</li>
    </ul>
  </li>
  <li><strong>Sofrosyni</strong>
    <ul>
      <li>Greek: σωφροσύνη</li>
      <li>Self-control, moderation and sound judgment. Literally “sound mind” (σώος “sound” + φρήν “mind”).</li>
    </ul>
  </li>
</ul>]]></content><author><name></name></author><category term="essay" /><summary type="html"><![CDATA[I just spent 2 hours correcting a list of supposedly untranslatable Greek words on eunoia.world.]]></summary></entry><entry><title type="html">10 Years of Adulthood</title><link href="https://annafilou.com/10-years/" rel="alternate" type="text/html" title="10 Years of Adulthood" /><published>2026-09-07T00:00:00+00:00</published><updated>2026-09-07T00:00:00+00:00</updated><id>https://annafilou.com/10-years</id><content type="html" xml:base="https://annafilou.com/10-years/"><![CDATA[<p>It recently occurred to me that I’m 28, which means I’ve been an adult for exactly <strong>10 years</strong>. It feels like a good time to reflect.</p>

<hr />

<p>When you’re in high school, ‘the adults’ love to tell you that these are the best years of your life. They say you’ll wish you could be 18 again; that being an adult sucks because you have a job and responsibilities.</p>

<p>Maybe that was true for them. It sounds like life was more linear and less free back then.</p>

<p>For me though, my 20s have been better than my teens in nearly every way. For example, today:</p>

<ul>
  <li>I look forward to work instead of dreading school. No contrived exercises, seemingly designed to bore me out of my mind, but real problems I can solve to grow and build a body of work I’m proud of.</li>
  <li>I decide what I do with my day and how I live my life. Nobody dictates my schedule anymore. (Which I admit, can sometimes be a negative, but it’s mostly positive.)</li>
  <li>I’m <a href="/getting-fit">stronger and healthier</a> as a result of more knowledge around fitness and practicing strength training.</li>
  <li>I’m treated and respected as a person. I don’t see this getting discussed enough: when you’re a kid, most adults treat you more like a pet than a human. Your thoughts, ideas, and agency often get overlooked, if not trampled.</li>
</ul>

<p>Teenage years do have one thing going for them: they’re full of firsts, and you can’t have those twice! That makes them vivid in memory and easy to be nostalgic about (I reminisce a lot), even when that period of your life was worse by objective measures.</p>

<hr />

<p>School wasn’t for me. You’re told what to do and how to do it, then judged on standardized tests you never wanted to take. Some people thrive in that system and that’s amazing, but I couldn’t. I stopped caring about subjects like chemistry and spent class time drawing, which disappointed my teachers and quite a few other people. I spent all day on the computer, following my interests down rabbit holes. I didn’t know what I wanted yet, but I knew what I <strong>didn’t</strong> want, and that was enough to guide me.</p>

<p>I should say I was also very lucky. I had my family’s support then and still do, so I never had to worry about putting food on the table. That gave me far more room to maneuver than many: I could say no to things that weren’t a good fit, trusting that something better would come along later.</p>

<hr />

<p><strong>In my 20s so far I’ve had five jobs and changed careers twice.</strong></p>

<p>My first career was operations management in intra-community imports and exports. (I wonder, does that sentence mean anything to anyone reading this?) I got good at it: built my own systems in no-code databases, became the person who could figure anything out, and set things up so everyone around me worked more efficiently. Within that little bubble, I was in demand. The problem was that I was bored and saw it as a dead end. Couldn’t imagine myself in that industry long term.</p>

<p>I’ve always been into computers (my parents love to tell people I knew how to type before I knew the alphabet), so that ended up leading me to web design and development. It’s a long story and one day I’ll write a blog post about it. The short of it is that I found work at a web design agency but the pay wasn’t good, so I quickly left to do operations again. This time though I had my own website and took on design gigs on the side. That eventually landed me a role at a <a href="/shopflix">Greek startup</a>, and later led me to my current role at a <a href="/jest">US startup</a>, which allowed me to spend a full month traveling across the US—a literal dream trip!</p>

<hr />

<p>I’ve made some good <a href="/friends">friends</a> in my 20s (mostly online) who support me personally and professionally, and whom I can have long, interesting conversations with. I’m also still close with friends from elementary and middle school, even if I rarely see most of them.</p>

<p>There’s plenty of room to improve, plenty of surface to build on, and I’m optimistic. I still have moments where everything feels pointless, but then I look back at how far I’ve come and imagine how much further I can go. These are turbulent times, in tech and in the world at large, and the only thing to do is keep moving forward.</p>

<p><strong>Here’s to the next 10 years.</strong></p>]]></content><author><name></name></author><category term="life" /><summary type="html"><![CDATA[It recently occurred to me that I’m 28, which means I’ve been an adult for exactly 10 years. It feels like a good time to reflect.]]></summary></entry><entry><title type="html">I made my own period app</title><link href="https://annafilou.com/period-app/" rel="alternate" type="text/html" title="I made my own period app" /><published>2026-08-24T00:00:00+00:00</published><updated>2026-08-24T00:00:00+00:00</updated><id>https://annafilou.com/period-app</id><content type="html" xml:base="https://annafilou.com/period-app/"><![CDATA[<p><img src="/assets/hema/hema-homescreen-icon.png" alt="Hema app icon on a phone home screen dock, between Phone and Safari" /></p>

<h2 id="tldr">TL;DR</h2>

<p>Clue started getting on my nerves, so I made my own alternative, <a href="https://hema-period.netlify.app/">Hema</a>. It’s a free, <a href="https://github.com/anna-filou/period-tracker">open-source</a> web app that works offline. You can export and import your data as a JSON file.</p>

<hr />

<h2 id="what-i-made">What I made</h2>

<p><img src="/assets/hema/hema-screens.png" alt="Three phone screenshots of Hema showing the calendar, log, and settings views" /></p>

<p>A super simple progressive web app called <a href="https://hema-period.netlify.app/">Hema</a> (from the Greek αίμα, aima → hema, meaning “blood”).</p>

<p>You can quasi “install” it and use it offline, even though it’s technically a website. You can export and import your data as JSON. Thankfully Clue also exports JSON, so all my periods from the past 9 years are already in it. You can’t import Clue exports directly into Hema (yet), but it’s trivial to hand the file to an LLM and ask it to convert it to Hema’s much simpler format.</p>

<p>It has everything I need and nothing I don’t:</p>

<ul>
  <li>A calendar where you log your period with a single tap. No menus, no save buttons.</li>
  <li>Optional flow heaviness (tap again to adjust), shown as taller and shorter bars.</li>
  <li>A log page to see previous periods and visually compare their duration.</li>
  <li>Fertile window prediction you can turn off.</li>
  <li>Monday as the default start of the week (or Sunday, one tap).</li>
  <li>The ability to exclude atypical periods so they don’t mess up predictions.</li>
</ul>

<p>What’s the catch?</p>

<ul>
  <li>No notifications. I haven’t found a reliable way to make PWA notifications work (even though it’s supposedly possible).</li>
  <li>You have to remember to back up your data; it can’t happen automatically.</li>
</ul>

<hr />

<h2 id="why-i-made-it">Why I made it</h2>

<p>I’ve been using <a href="https://helloclue.com/">Clue</a> for almost 10 years. When I first started, it was pretty good. What stood out at the time was the neutral styling: red for blood, blue for ovulation, no flowers, stickers, or cutesy pink graphics. Every other period app looked too childish for my taste.</p>

<h2 id="the-deterioration-of-clue">The deterioration of Clue</h2>

<p>But over the years it slowly became <a href="https://en.wikipedia.org/wiki/Enshittification">enshittified</a>.</p>

<p>Full-screen premium pop-ups every time I opened the app were one thing (devs have to make money after all, that’s fair). But then came a “content” tab with articles like “Where is the clitoris?” (which, considering the target audience, I find <strong>infantilizing</strong>), constant promos for new features I didn’t want, surveys, and partnerships with hardware I wasn’t using.</p>

<p><img src="/assets/hema/clue-annoyances.png" alt="Clue screenshots showing the content tab, Clue Plus promotions, and in-app survey and upsell modals" /></p>

<p>But what really made me think “I’m gonna make my own fucking app” was the notifications like “It is now your luteal phase! Find out what’s happening”, which you can’t turn off without also disabling the period prediction reminders.</p>

<figure>
  <img src="/assets/hema/clue-phase-notifications.png" alt="Clue push notifications about early luteal and late follicular phases" />
  <figcaption><a href="https://developer.android.com/develop/ui/compose/notifications/channels">Android has had notification channels</a> for over a decade. I asked Clue years ago in a review to use them. They even replied, but nothing came of it.</figcaption>
</figure>

<figure>
  <img src="/assets/hema/clue-oura-ring-banner.png" alt="Clue Oura Ring promotion banner, and a toast saying the banner has been hidden for 1 month" />
  <figcaption>Tapping “Hide this banner” on the Oura Ring promotion notified me that the banner has been hidden for a month. I’m never gonna get an Oura ring; I don’t wanna see this again in a month! And this is just one of their countless banners.</figcaption>
</figure>

<figure>
  <img src="/assets/hema/clue-trying-to-conceive-banner.png" alt="Clue banner reading “Trying to conceive? We're here to help.” with Hide this banner and Learn more actions" />
  <figcaption>For a time they even kept asking me if I’m trying to conceive, which I found <strong>infuriating</strong> because I kept having to hide this banner and it kept coming back!</figcaption>
</figure>

<p>Meanwhile, every few updates, features I liked disappeared. For example, flow intensity used to be represented by taller and shorter bars in the calendar—now it’s color-coding that’s harder to parse at a glance. You used to be able to compare cycle lengths visually; that vanished too. And still no way to set Monday as the first day of the week!</p>

<p>All in all, I was getting more and more frustrated with Clue, until this weekend, when I told myself enough is enough and got to work with Cursor.</p>]]></content><author><name></name></author><category term="essay" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">Why are pronouns gendered at all?</title><link href="https://annafilou.com/why-are-pronouns-gendered-at-all/" rel="alternate" type="text/html" title="Why are pronouns gendered at all?" /><published>2026-04-13T00:00:00+00:00</published><updated>2026-04-13T00:00:00+00:00</updated><id>https://annafilou.com/why-are-pronouns-gendered-at-all</id><content type="html" xml:base="https://annafilou.com/why-are-pronouns-gendered-at-all/"><![CDATA[<p>Preferred pronouns are a hotly debated topic in the USA these days (at least judging by the amount of media coverage). It feels like everyone is arguing about which pronouns to use<sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup>, but nobody seems to be asking why pronouns are gendered in the first place.</p>

<p>Think about it. Why does your gender have to be part of every single sentence that’s ever spoken or written about you?</p>

<p>Imagine a pronoun specifically for Black people. Imagine that, if talking about a Black man, you had to use “ze” instead of “he” for your English to be “grammatically correct”. I’m sure there would be people who’d say, “It’s not racist, it’s just grammar!” But you and I both know, it would be racist as fuck. Why else would you create a pronoun to refer to a specific group of people, grouped by an arbitrary characteristic that you decided is socially important?</p>

<p>Now, I know this isn’t a perfect analogy. In my hypothetical scenario, we’d be making a new pronoun out of the blue, but for all we know, he and she have been with us since the dawn of time. (Which isn’t true, by the way. And while many languages have gendered pronouns, many do not.)</p>

<p>It’s still worth wondering why personal pronouns came to be gendered in the first place. I don’t know the answer to that, and it’s likely nobody ever will. But my guess is that it had something to do with social status and hierarchy. I’m guessing that because of how we treat animate (he/she) vs inanimate (it) pronouns today: it would be offensive to call a human “it”, but it’s OK to call a dog that. <code class="language-plaintext highlighter-rouge">He/she &gt; it</code>. Are he and she equal? Perhaps today. Is it a stretch to imagine it used to be <code class="language-plaintext highlighter-rouge">he &gt; she &gt; it</code>? After all, in many parts of the world, that hierarchy is still very much alive.</p>

<p>Are you starting to see my problem with gendered pronouns?</p>

<p>I still remember stumbling upon this experiment that found that simply asking female students to fill out a demographic questionnaire before a math test, thereby reminding them of their gender, negatively affected their scores.<sup id="fnref:2"><a href="#fn:2" class="footnote" rel="footnote" role="doc-noteref">2</a></sup> Guess what gendered pronouns do? Remind people of their gender! And of the fact that their gender is so significant that it has to be mentioned, regardless of what is being said about them.</p>

<p>If I say “she is a doctor”, you know I’m talking about a female human. But you know nothing else. What is their hair color? Skin color? Age? Doesn’t matter! If it did, I could specify (“She is 32 years old. She has blond hair.”) But gender? Well, that one characteristic is so important for some reason that I just need to mention it to be “grammatically correct”.</p>

<p>Humans reproduce through a binary sex system: male sperm fertilizes a female egg. That’s not up for debate.<sup id="fnref:3"><a href="#fn:3" class="footnote" rel="footnote" role="doc-noteref">3</a></sup></p>

<p>But choosing to divide the population based on reproductive biology, and use different pronouns to refer to them, and making it a grammatical necessity that we use these pronouns in almost every sentence… well, those are arbitrary decisions our society has made, and can therefore undo.</p>

<p>I hope the current discourse around pronouns leads people to question why they are gendered at all. That’s the conversation I want to have.</p>

<hr />

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1">
      <p>Spoiler: those each person asks you to use. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2">
      <p><a href="https://www.semanticscholar.org/paper/Stereotype-Threat-in-Applied-Settings-Re%E2%80%90Examined-Danaher-Crandall/7264aace8bc0f199fce2f604419ef277931b8558">Stereotype Threat in Applied Settings Re‐Examined</a>. And here’s another more <a href="https://spsp.org/news/character-and-context-blog/wu-boys-girls-math-performance">recent, related study</a>. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:3">
      <p>Intersex people don’t contradict this. The term describes people whose secondary sex characteristics don’t align with their reproductive biology (and in very rare cases, people whose organs are in-between or both male and female), not a third reproductive category. <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name></name></author><category term="essay" /><summary type="html"><![CDATA[Preferred pronouns are a hotly debated topic in the USA these days (at least judging by the amount of media coverage). It feels like everyone is arguing about which pronouns to use1, but nobody seems to be asking why pronouns are gendered in the first place. Spoiler: those each person asks you to use. &#8617;]]></summary></entry><entry><title type="html">My work at Jest</title><link href="https://annafilou.com/jest/" rel="alternate" type="text/html" title="My work at Jest" /><published>2026-02-26T00:00:00+00:00</published><updated>2026-02-26T00:00:00+00:00</updated><id>https://annafilou.com/jest</id><content type="html" xml:base="https://annafilou.com/jest/"><![CDATA[<p><img src="/assets/jest/profiles-3.webp" alt="Jest.com profile screen on phone with fanned-out user profile cards." /></p>

<p><a href="https://about.jest.com/">Jest</a> is the first marketplace for messaging games—a real alternative to the app store model.</p>

<p>As the team’s Product Designer, I help shape how the platform looks, feels, and behaves. My work spans early concepting, product flows, UI design, and product management.</p>

<figure>
  <img src="/assets/jest/jest-techcrunch.webp" alt="Screenshot of TechCrunch article: Jest, a marketplace for messaging games, is challenging the app store status quo." />
  <figcaption><a href="https://techcrunch.com/2026/02/26/jest-a-marketplace-for-messaging-games-is-challenging-the-app-store-status-quo/">TechCrunch coverage</a>, February 2026.</figcaption>
</figure>

<ul>
  <li>We’re live in the US on <a href="https://jest.com/">Jest.com</a></li>
  <li>Learn more on our corporate website, <a href="https://about.jest.com/">about.jest.com</a></li>
  <li>If you’re a game developer or studio, check out the <a href="https://about.jest.com/fund/">Jest Games Fund</a> for up to $1M in support to publish your game on Jest!</li>
</ul>]]></content><author><name></name></author><category term="case study" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">Smart Carousels with CSS</title><link href="https://annafilou.com/carousels/" rel="alternate" type="text/html" title="Smart Carousels with CSS" /><published>2026-01-07T00:00:00+00:00</published><updated>2026-01-07T00:00:00+00:00</updated><id>https://annafilou.com/carousels</id><content type="html" xml:base="https://annafilou.com/carousels/"><![CDATA[<p>You’ve undoubtedly seen many carousels on the web. You know how usually the content gets cut off?</p>

<p><img src="/assets/carousel-cutoff.webp" alt="" /></p>

<p>The issue arises because, when designing for the web, we need content to have a <strong>maximum width</strong>. Otherwise, if someone has a wide monitor, the layout looks broken or they have to move their head all the way from left to right to read it.</p>

<p>When we give containers a maximum width, anything that doesn’t fit inside them gets cut off and becomes invisible. In a carousel, that means as you scroll, the content disappears abruptly before the end of the window. (Unless the window is narrower than the max width you set. In other words, this isn’t a problem on mobile.)</p>

<p>Everything on a website is a box. The carousel is also a box. When you put something in the box, it appears on the leftmost side. If you want it to show up more to the right, you can add padding on the left. So hypothetically, we could add padding to align the first book with the left edge of the other sections! Alas… the padding would need to be different depending on the window’s width!</p>

<p>So for a long time, I thought this was an unavoidable problem. But then I saw <a href="https://www.apple.com/iphone/">a carousel that worked right on Apple’s website</a>! So… there was a way!</p>

<p>Thankfully, because this is the web, you can right-click → Inspect Source on any website to see exactly how it’s built. I then adapted it for my website, and ta-da!</p>

<figure>
<video autoplay="" loop="" muted="" src="/assets/carousel-demo.mp4" class="w-100 br4"></video>
<figcaption><a href="/reading">See it live</a></figcaption>
</figure>

<p>The code ↴</p>

<div class="language-scss highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$container</span><span class="p">:</span> <span class="m">1240px</span><span class="p">;</span> <span class="cm">/* Yes, I use Sass. Yes, I know we have CSS variables now, but I like it and the pre-processor is built into Jekyll, which builds my site anyway! */</span>
<span class="nv">$container-padding</span><span class="p">:</span> <span class="m">32px</span><span class="p">;</span>

<span class="nc">.book-carousel</span> <span class="p">{</span>
    <span class="nl">padding</span><span class="p">:</span> <span class="m">0</span> <span class="nf">calc</span><span class="p">(</span><span class="m">50%</span> <span class="o">-</span> <span class="nf">min</span><span class="p">(</span><span class="nv">$container</span><span class="o">,</span> <span class="m">100%</span><span class="p">)</span> <span class="o">/</span> <span class="m">2</span> <span class="o">+</span> <span class="nv">$container-padding</span><span class="p">);</span> <span class="cm">/* [Half the screen] - [half the container] + [container padding * 2] */</span>
    <span class="nl">overflow-x</span><span class="p">:</span> <span class="nb">auto</span><span class="p">;</span> <span class="cm">/* makes it horizontally scrollable */</span>
    <span class="nl">scroll-snap-type</span><span class="p">:</span> <span class="nb">x</span> <span class="nb">proximity</span><span class="p">;</span> <span class="cm">/* so you can’t stop in between books: it “snaps” to the closest element in the X axis */</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The magic part is:</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code>calc(50% - min($container, 100%) / 2 + $container-padding);
</code></pre></div></div>

<p>We’re basically saying:</p>
<ul>
  <li>Take half of the screen.</li>
  <li>Subtract half of the max-width container from it OR half the screen (in which case the result is 0), whichever is smaller. This gives us the effective margin on each side.</li>
  <li>Add the container padding. Now we have <strong>the exact distance between the content of the other sections and the edge of the viewport</strong> on each side!</li>
</ul>

<p><img src="/assets/carousel-diagram.webp" alt="" /></p>

<p>And the coolest part is that this is all just CSS! Which means, if scripts don’t load (bad connection, on the train, unknown error, browser that blocks scripts), the carousel still works the same (progressive enhancement 😎).</p>

<hr />

<p>Did you notice the custom scrollbar? Don’t ask me how that one works because I asked Cursor to build it. You can <a href="https://github.com/anna-filou/anna-filou.github.io/blob/master/assets/js/book-carousel-scrollbar.js">see the code on GitHub</a> though.</p>]]></content><author><name></name></author><category term="product" /><summary type="html"><![CDATA[You’ve undoubtedly seen many carousels on the web. You know how usually the content gets cut off?]]></summary></entry><entry><title type="html">How I build websites</title><link href="https://annafilou.com/how-websites/" rel="alternate" type="text/html" title="How I build websites" /><published>2026-01-05T00:00:00+00:00</published><updated>2026-01-05T00:00:00+00:00</updated><id>https://annafilou.com/how-websites</id><content type="html" xml:base="https://annafilou.com/how-websites/"><![CDATA[<p><img src="/assets/how-websites/hero.webp" alt="" /></p>

<p>I’ve been building websites for over 7 years, but until now I’d never shared my entire process online.</p>

<p>Everyone is talking about Framer and Webflow, and most build with WordPress. <strong>I do things differently</strong>. Not to be contrarian, but because I prefer having more freedom.</p>

<p>The post gets a bit technical at times, but <strong>if you don’t consider yourself technical, it’s still very much worth reading</strong> (regardless of whether you’re thinking about working with me). It’ll give you a practical understanding of how the web works.</p>

<hr />

<h2 id="table-of-contents">Table of contents</h2>
<ul>
  <li><a href="#my-approach">My approach</a></li>
  <li><a href="#going-live-hosting">Going live: Hosting</a></li>
  <li><a href="#making-sites-editable">Making sites editable</a></li>
  <li><a href="#templating-languages">Templating Languages</a></li>
  <li><a href="#getting-a-domain-name">Getting a domain name</a></li>
  <li><a href="#setting-up-custom-email">Setting up custom email</a></li>
</ul>

<hr />

<h2 id="my-approach">My approach</h2>

<p>I hand code websites using <a href="https://developer.mozilla.org/en-US/docs/Web/HTML">HTML</a>, <a href="https://developer.mozilla.org/en-US/docs/Web/CSS">CSS</a> and a bit of <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript">JavaScript</a>.</p>

<p>If you’re new to this, just know that HTML is a file type and websites are just folders with files that are linked to each other. You know how you open <code class="language-plaintext highlighter-rouge">.docx</code> files using Word? Well, you open <code class="language-plaintext highlighter-rouge">.html</code> files using a web browser, like Chrome!</p>

<p>I use <a href="https://jekyllrb.com/">Jekyll</a>, a Static Site Generator (SSG), to ‘sandwich’ together (“bundle”) parts of my code (e.g. navigation bar, footer, etc.) into a full website. Jekyll, like <a href="https://jamstack.org/generators/">other SSGs</a>, runs on my computer and I control it via terminal commands.</p>

<p><img src="/assets/how-websites/editor.webp" alt="" /></p>

<p>The reason I do that instead of just making one HTML file per webpage is that some elements repeat across pages (e.g. head, nav, footer) and some pages look exactly the same but have different content (think individual articles in a news site, or the same pages in different languages). I don’t wanna do duplicate work and risk creating inconsistencies. Even if a website has a single page at first, I might add more later. And even if I don’t, it’s often helpful to have separate files for different sections because it’s easier to find where to make changes when needed.</p>

<p>Jekyll creates a folder within my project folder called <code class="language-plaintext highlighter-rouge">_site</code> and in it it puts the sandwiched version. That version works completely independently and offline (as all sites do), unless I have built any dependencies into the code itself (for example, if I embed a YouTube video, it’s not gonna play offline).</p>

<h2 id="going-live-hosting">Going live: Hosting</h2>

<p>To put the website on the internet, I use <a href="https://netlify.app/">Netlify</a>, a <a href="https://en.wikipedia.org/wiki/Content_delivery_network">Content Delivery Network</a> (CDN). They offer free hosting, and since they’re a CDN, that means they put a copy of my website (<code class="language-plaintext highlighter-rouge">_site</code> folder) on many servers across the globe, and they serve from the one closest to the visitor for increased speed.</p>

<p><img src="/assets/how-websites/netlify.webp" alt="" /></p>

<p>Netlify can actually use Jekyll (among others) on their side to ‘sandwich’ (bundle) the code I upload. So I don’t have to upload the finished <code class="language-plaintext highlighter-rouge">_site</code> folder; instead I connect it to <a href="http://github.com/">GitHub</a> directly and Netlify rebuilds the site every time I push a change.</p>

<p>Note: Since Netlify builds the site independently from me, I might occasionally run into issues where the site gets built fine on my computer, but Netlify runs into errors. These are usually because of different <a href="https://www.ruby-lang.org/en/">Ruby</a> versions (the language powering Jekyll) running on Netlify’s servers vs locally on my machine. To resolve them I typically have to make changes to the “<a href="https://jekyllrb.com/docs/step-by-step/10-deployment/#gemfile">Gemfile</a>”, a text file that tells Jekyll which version of what to use.</p>

<h2 id="making-sites-editable">Making sites editable</h2>

<p><img src="/assets/how-websites/cms.webp" alt="" /></p>

<p>But how does a non-technical person (e.g. my client) edit their website if the content is stored in the code?</p>

<p>Well, Jekyll &amp; Co. let us “pull in” data from text files (<a href="https://en.wikipedia.org/wiki/Markdown">Markdown</a> and <a href="https://en.wikipedia.org/wiki/YAML">YML</a>, a more human-readable way to write <a href="https://en.wikipedia.org/wiki/JSON">JSON</a>) to put into our code. It’s still confusing for most people to edit YML files though, and more importantly, they might accidentally change the formatting (it takes just adding or removing a single space!) and break the whole thing. Thankfully there exist programs called <strong>Git-based Content Management Systems</strong> (CMS). They let people edit specific sections within files on GitHub through a simple interface, without letting them change parts we don’t explicitly allow.</p>

<p>I’ve successfully used <a href="https://pagescms.org/">Pages CMS</a> a bunch of times. It looks good and works well, but it’s missing many features. In the past I’ve used <a href="https://decapcms.org/">Decap CMS</a> back when it was <strong>Netlify CMS</strong>, but the interface was not as intuitive for editors.</p>

<p>To set up a Git-based CMS, you typically need to create a text file to tell the CMS what inputs (text, dropdown, etc.) to present to the user and what information these should alter in which file. (It’s a tedious process but ChatGPT can help.)</p>

<h3 id="alternative-cms-options">Alternative CMS options</h3>

<p>Git-based CMS is not the only option. There are also API-based CMSs, and they work by letting us store data (text, images…) on their servers, and then making that data available to us via an <a href="https://en.wikipedia.org/w/index.php?title=API">API</a>. Think of it like asking Jekyll to pull in data from a remote server, instead of a YML file in the same parent folder. We can pull in data each time I build the website so it’s part of the shipped code (good), or inject it into the live website each time somebody visits it (bad if it can be avoided, because we introduce latency and need JavaScript for it to work).</p>

<p>The upside of API-based CMS is that you can use the same data to power multiple “clients” (e.g. a website, an iOS App, an Android app, a POS…). The downside is that your data is not yours; if the CMS company goes away, so does the data. Or they might increase their prices and you’ll be almost forced to start paying them more, because changing an older project to use a different CMS is often cumbersome.</p>

<p>And a third option is traditional “monolithic” CMS, like <a href="https://wordpress.com/">WordPress.com</a>. Monolithic because they take care of both the website generation and the content management (think of it like Jekyll + Pages CMS into one). All-in-one might sound practical, but it forces you to use certain patterns you might not like or need for a project because you can’t cherry pick the parts you like—it’s all or nothing.</p>

<p>For example, let’s say I like Wordpress’ content editing part because it’s easy for clients to use (not really—it’s terrible, but let’s pretend) but I don’t like writing <a href="https://en.wikipedia.org/wiki/PHP">PHP</a> to create my page templates, nor do I want to rent server space and install and manage Wordpress updates. If I want to use Wordpress, I have to do all of these together. But with “decoupled” CMS (whether Git- or API-based), I can switch each part individually. I might be using PagesCMS and then switch to Decap by changing a single text file (configuration) without having to give up Jekyll. Or the opposite! I might switch from Jekyll to, say, <a href="https://gohugo.io/">Hugo</a>, without giving up PagesCMS.</p>

<h2 id="templating-languages">Templating Languages</h2>

<p>This decoupling can go even further, as many SSGs let you choose which templating language you want to use. Jekyll uses <a href="https://shopify.github.io/liquid/">Liquid</a>, but other SSGs, like <a href="https://www.11ty.dev/">Eleventy</a>, let you choose between many, including Liquid, <a href="https://handlebarsjs.com/">Handlebars</a>, <a href="https://mustache.github.io/">Mustache</a>, and more. Templating languages generally all work the same way. They have an opening and closing symbol combination (often <code class="language-plaintext highlighter-rouge">{{</code> and <code class="language-plaintext highlighter-rouge">}}</code>, hence names like “Mustache”) that are not natively part of HTML. That way, the templating language can recognize its parts and replace them with the thing you specify. For example, I might use Liquid inside HTML to write:</p>

<div class="language-liquid highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&lt;a href="<span class="cp">{{</span><span class="w"> </span><span class="nv">site</span><span class="p">.</span><span class="nv">data</span><span class="p">.</span><span class="nv">links</span><span class="p">.</span><span class="nv">search</span><span class="p">.</span><span class="nv">url</span><span class="w"> </span><span class="cp">}}</span>"&gt;<span class="cp">{{</span><span class="w"> </span><span class="nv">site</span><span class="p">.</span><span class="nv">data</span><span class="p">.</span><span class="nv">links</span><span class="p">.</span><span class="nv">search</span><span class="p">.</span><span class="nv">title</span><span class="w"> </span><span class="cp">}}</span>&lt;/a&gt;
</code></pre></div></div>

<p>The part inside the brackets is Liquid, and the rest is HTML. Assuming I’m using Jekyll to build the website, for the above to work, there needs to be a file called <code class="language-plaintext highlighter-rouge">links.yml</code> inside a folder named <code class="language-plaintext highlighter-rouge">_data</code> inside the parent folder that includes all the website’s files (<code class="language-plaintext highlighter-rouge">site</code>). Inside that <code class="language-plaintext highlighter-rouge">links.yml</code> I need to have</p>

<div class="language-yml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">links</span><span class="pi">:</span>
<span class="err">	</span><span class="pi">-</span> <span class="s">search</span>
<span class="na">		title</span><span class="pi">:</span> <span class="s">Google</span>
<span class="na">		url</span><span class="pi">:</span> <span class="s">https://google.com</span>
</code></pre></div></div>

<p>Then Jekyll will know to replace the Liquid snippets above and produce:</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;a</span> <span class="na">href=</span><span class="s">"https://google.com"</span><span class="nt">&gt;</span>Google<span class="nt">&lt;/a&gt;</span>
</code></pre></div></div>

<p>And that will be the code in the outputted HTML inside my <code class="language-plaintext highlighter-rouge">_site</code> folder.</p>

<h2 id="getting-a-domain-name">Getting a domain name</h2>

<p><img src="/assets/how-websites/domains.webp" alt="" /></p>

<p>All that is great, but how does someone visit my website on the internet? I want them to type something like <code class="language-plaintext highlighter-rouge">example.com</code> into their browser and see my page. To do that, I need to buy the domain name “example.com”. I buy domains from companies known as domain registrars. <a href="https://iwantmyname.com/">iwantmyname.com</a> is one such company and while I appreciated their no-nonsense minimalist approach for years, their prices have gone up significantly lately. So I switched to buying from <a href="https://porkbun.com/">Porkbun</a>!</p>

<p>After I buy a domain, I need to point it to where my website is stored (‘hosted’). I do that by adding a <a href="https://en.wikipedia.org/w/index.php?title=Domain_Name_System">DNS</a> record in the domain registrar’s software platform. What does the record say? Depends on where the site is hosted. In my case, that’s usually Netlify, so Netlify gives me some IP addresses to copy-paste and they take care of the rest.</p>

<p><img src="/assets/how-websites/dns.webp" alt="" /></p>

<h2 id="setting-up-custom-email">Setting up custom email</h2>

<p>What if I want to receive email in an address like <code class="language-plaintext highlighter-rouge">me@example.com</code>?</p>

<p>First, I need an email service provider. Gmail is such a provider, but to use it with a custom domain, you need to buy a “Google Workspace” subscription. Most email services ask you to pay to use a custom domain email.</p>

<p>The only reliable free solution that I know of is <a href="https://www.zoho.com/mail/">Zoho Mail</a>, but that too has a catch: when using the free version of the service, you can only view your emails from their website or their mobile app. Good enough, considering it’s free! But for just 12 € per <strong>year</strong> (not per month), you can use any email client you like (for example Apple Mail, Outlook, or even Gmail—yes, Gmail can be used as an email client for other services!) via the protocols <a href="https://en.wikipedia.org/wiki/Internet_Message_Access_Protocol">IMAP</a> (receiving email) &amp; <a href="https://en.wikipedia.org/w/index.php?title=Simple_Mail_Transfer_Protocol">SMTP</a> (sending email) or <a href="https://en.wikipedia.org/wiki/Post_Office_Protocol">POP3</a> (both).</p>

<p><img src="/assets/how-websites/email.webp" alt="" /></p>

<hr />

<p>And now you know how I make websites! Of course the process is subject to change. I love trying out all the latest tools, but I’ve been loyal to Jekyll for so long because it just… works.</p>

<p>The Git-based CMS landscape on the other hand changes constantly, so every few years I need to switch to something else. It’s not a huge deal, because the data always remains accessible and editable (remember the YML files?), since it’s decoupled from the CMS.</p>

<p>And that’s the whole point of this approach: you’re never locked in. If a tool stops working for you, you can swap it out without losing your content or starting from scratch. And that flexibility benefits everyone: clients get sites that will last, and collaborators get a flexible stack that’s easy to work with!</p>

<p><strong>Questions? Suggestions?</strong> Reach out—I’m all ears!</p>]]></content><author><name></name></author><category term="product" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">Why I built Today Todo</title><link href="https://annafilou.com/building-today/" rel="alternate" type="text/html" title="Why I built Today Todo" /><published>2025-10-12T00:00:00+00:00</published><updated>2025-10-12T00:00:00+00:00</updated><id>https://annafilou.com/building-today</id><content type="html" xml:base="https://annafilou.com/building-today/"><![CDATA[<p><img src="/assets/today-todo-4x3.webp" alt="3 mockups showing a minimal todo app in dark mode. The third screen is of interest: it shows a modal with the title “it’s a new day”, a list of todos, and a button that reads “Clear and Start Today”" /></p>

<p>Like many tech workers, I have a complicated relationship with to-do apps. On one hand, I’ve spent countless hours trying them all—and even making my own. On the other, they just. Don’t. Work.</p>

<p>I’ve literally tried them all: Todoist, Microsoft To Do, Sunsama, Trello, Superlist, Taskade… and I’ve built at least two fully custom, complicated task management systems in Coda, with features like automatic prioritization based on parameters and warnings when there aren’t enough hours in the day to finish everything I’ve scheduled.</p>

<p>They all meet the same fate. It doesn’t matter how much I like them at first, how motivated I feel, or how productive I get—eventually I’ll miss a day or two. Then, when I come back, I’m greeted by an overwhelming list of overdue tasks—exactly what I was trying to <strong>avoid</strong> in the first place.</p>

<figure>
  <img src="/assets/todo-archive-microsoft.webp" alt="Screenshot of a bloated task list" />
  <figcaption>Many of the tasks I add to a task manager are by nature <strong>ephemeral</strong>, like “call hotel for reservation” or “tidy up clothes drawer.” I’ve long since completed them (or not), and yet they’ve been sitting there for years. Is that helping me?</figcaption>
</figure>

<h2 id="second-brain-anyone-">Second brain, anyone? 🧠</h2>

<p>I’ve seen the second-brain systems. They make so much sense: capture every idea, throw it into your inbox for later review, spend five minutes at the end of the day deciding what goes where, and once a month review everything to prioritize what matters. Human memory is fragile, but the app never forgets.</p>

<p>Sounds great!</p>

<p>Except I never look at my inbox. I never <strong>feel</strong> like looking at my inbox—the thought alone overwhelms me. It’s exciting for a few days (“think how much my future self will thank me!” Not…), but the motivation always fades. Before long, I’ve left behind another digital graveyard of things I once thought I should do.</p>

<p>The promise of these apps is that they’ll let us capture everything so we can rest easy knowing we won’t forget. But that’s the problem: <strong>they never let us forget!</strong> The constant reminder of unfinished tasks clutters my brain.</p>

<blockquote>
  <p>Forgetting is a feature of memory, not a bug. You let the unimportant stuff fade so you can focus.</p>
</blockquote>

<p>I know, you don’t <strong>have</strong> to see all your tasks at once. You can focus on what’s due today while everything else sits in the backlog. But I <strong>know</strong> it’s there, and it stresses me out. What if I missed a few things two days ago, and then another yesterday? I open the app and see a growing list of overdue tasks. Some people can calmly sort through them—decide what’s still important, move things around, delete the rest.</p>

<p>I’m not one of those people. I’m a hoarder. I have a hard time throwing things away—or removing apps from my phone—and that extends to tasks. What if I need them again someday?</p>

<h2 id="what-works">What works</h2>

<p>You know what’s actually worked for me, for years?</p>

<p>A paper notebook. <sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup></p>

<p><img src="/assets/todo-notebook.webp" alt="Notebook spread with sketches on the left page and a tight list of tasks with checkboxes of various states on the right" /></p>

<p>I write tasks down as they come. When I finish one, I check it off. A single page usually lasts me a few days or weeks. When it fills up, I turn the page and I’m forced to make decisions: <strong>which uncompleted tasks do I bring over?</strong></p>

<p>That <strong>friction</strong> of having to manually re-write incomplete tasks forces me to ask whether they’re actually worth doing. And that’s what to-do apps have been missing!</p>

<p>On paper, the default is that incomplete tasks “disappear” when you turn the page. In digital apps, the default is that they become “overdue” and haunt you. Even if they get hidden in a backlog, I still know they’re there—and that knowledge alone creates <strong>guilt</strong>. I end up browsing through old tasks, resurrecting ultimately useless ones just because I feel bad for not having done them.</p>

<h2 id="the-digital-equivalent">The digital equivalent?</h2>

<p>I built my own to-do app where, at the end of the day, unfinished tasks just… <strong>vanish</strong>. They go away! Better yet, they don’t <strong>just</strong> vanish. When you open the app in the morning, it shows you the list of tasks you didn’t finish yesterday. There’s only one possible action: <strong>delete the list</strong>! You can’t roll tasks over to the next day.</p>

<p>If you see something important—something you actually want to do—you have to remember it for a few seconds and re-write it yourself. How many unimportant tasks survive that process? Not many, maybe none! And that’s the point: no backlog, no guilt.</p>

<p><img src="/assets/today-todo-modals.webp" alt="Two screens showing two different modals: One says &quot;Welcome&quot; and explains how the app works. The other shows it's a new day. Here are the tasks you didn't finish yesterday, are they still important? If yes, add them back from memory  Beneath the list of tasks, there is a button that reads &quot;Clear&quot; and &quot;Start Today&quot;" /></p>

<h2 id="try-it">Try it!</h2>

<p>It’s surprisingly freeing. You should try it—and you can! <a href="https://today.annafilou.com/">Right here</a>.</p>

<p>There’s a link in the settings to email me feedback if you’d like.</p>

<p>Note: it’s a Progressive Web App, not just a website. You can “install” it and use it offline! <a href="https://www.cdc.gov/niosh/mining/tools/installpwa.html">Here’s how</a>.</p>

<hr />

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1">
      <p>I recently switched to an E-Ink writing tablet—the Onyx Boox Go 10.3”. Highly recommended if you’re into that sort of thing. <img src="/assets/onyx-cafe.webp" alt="A tablet with an E-Paper screen on a table in a cafe. Latte visible in the background. Hand visible holding a Wacom pen." /> <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name></name></author><category term="product" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">My work at Shopflix</title><link href="https://annafilou.com/shopflix/" rel="alternate" type="text/html" title="My work at Shopflix" /><published>2025-05-26T00:00:00+00:00</published><updated>2025-05-26T00:00:00+00:00</updated><id>https://annafilou.com/shopflix</id><content type="html" xml:base="https://annafilou.com/shopflix/"><![CDATA[<p>From April 2023 until October 2025 I was working as a UI / Product Designer at <a href="https://shopflix.gr/">Shopflix</a>, a major e-commerce marketplace in Greece.</p>

<p>I was initially brought on for UI Design, but over time my role evolved into what we now call Product Design, spanning everything from visual design to component systems and behavior analytics.</p>

<p>I can’t share details due to the NDA, but here’s the gist of my 2.5 years at Shopflix:</p>

<h3 id="year-1">Year 1</h3>
<p>I spent most of my time patching up existing designs as they were being implemented, and rushing to design new features using problematic components in the name of speed and consistency. Alongside that I was creating ad-hoc marketing assets while building a component library in Figma and laying the foundations of a design system on the side.</p>

<p>Due to the replatforming taking place at the same time, rethinking flows was off the table. I hated adapting work I believed was poorly thought-out, but I developed something unique:</p>

<p><strong>I turned complete pages into components</strong> (with variables) <strong>that I could drop into any flow, ensuring all user journeys would always display the latest version</strong>. This solved a major issue: developers would often start working on a feature many months after I’d designed it, and by then there were updates to pages within that flow. Before this approach, they kept accidentally rolling back each other’s work because each person was looking at a different version!</p>

<p>Here’s the component system in action:</p>

<figure>
  <video autoplay="" loop="" muted="" src="/assets/shopflix/shopflix-checkout-cart-components.mp4" class="w-100 br3"></video>
  <figcaption>Screen recording showing real-time interaction with checkout and cart component instances, toggling variants like device type (desktop/mobile) with instant page updates.</figcaption>
</figure>

<h3 id="year-2">Year 2</h3>
<p>With a major deadline gone, I finally had the freedom to explore and pitch improvements. But most of my usability-focused proposals initially got shelved.</p>

<p>That phase taught me as much about organizational dynamics as it did about design at scale. I gradually built stakeholder buy-in by consistently shipping good work, sharing honest opinions, and pushing back when needed. I also got involved with anything I could help improve, even outside my defined role.</p>

<h3 id="year-3">Year 3</h3>
<p>My persistence paid off because on Year 3 an organizational shift allowed me to work on the kind of projects I wanted to from the beginning: remaking core flows from scratch.</p>

<p>As of writing this, the bulk of my design work has not been implemented yet (so I can’t show it here 😮‍💨), but it includes major updates for the:</p>
<ul>
  <li>Checkout Flow</li>
  <li>Product Page</li>
  <li>Homepage</li>
  <li>Orders</li>
  <li>Cart</li>
</ul>

<p>We’d long been aware of the shortcomings, but conflicting priorities did not previously allow the time to address them. I can’t describe the satisfaction I felt seeing the enormous usability improvements and it goes without saying that I can’t wait to see them live!</p>

<p>I left Shopflix knowing it’s on a much better trajectory than when I joined, and I’m confident that the team will continue doing great work to bring the platform to the state we know it can reach!</p>]]></content><author><name></name></author><category term="case study" /><summary type="html"><![CDATA[From April 2023 until October 2025 I was working as a UI / Product Designer at Shopflix, a major e-commerce marketplace in Greece.]]></summary></entry><entry><title type="html">How I generate color scales in CSS with OKLCH</title><link href="https://annafilou.com/css-color-scales/" rel="alternate" type="text/html" title="How I generate color scales in CSS with OKLCH" /><published>2025-05-13T00:00:00+00:00</published><updated>2025-05-13T00:00:00+00:00</updated><id>https://annafilou.com/css-color-scales</id><content type="html" xml:base="https://annafilou.com/css-color-scales/"><![CDATA[<p><img src="/assets/anna-color-scale-css.webp" alt="" /></p>

<h2 id="the-idea">The idea</h2>

<p>I wanted to create a single variable in my CSS, e.g. <code class="language-plaintext highlighter-rouge">--brand: #ff6800;</code>, and have an entire color scale (with variables like <code class="language-plaintext highlighter-rouge">--brand-10: #ffe4d3; --brand-20: #ffd2b2;</code> and so on) automatically “generated” for me. Like this! ⤵︎</p>

<p><img src="/assets/color-scale-example.webp" alt="" /></p>

<p>Similar to what you get from sites like <a href="https://uicolors.app/generate">uicolors.app’s Tailwind CSS Color Generator</a>, but locally, in your CSS file.</p>

<p>Why? When playing around with a new design, not yet sure which colors to go with, being able to tweak a couple of values directly in my CSS and preview my own design in different colors would be super practical.</p>

<p>Now, you <em>might</em> be wondering:</p>

<h2 id="what-is-oklch">What is OKLCH?</h2>

<p>These people have done a much better job explaining than I could at the moment:</p>

<ul>
  <li>
    <p><a href="https://evilmartians.com/chronicles/oklch-a-color-picker-made-to-help-think-perceptively">OK, OKLCH: a color picker made to help think perceptively, by Evil Martians</a></p>

    <p>“OKLCH is <strong>a new way of encoding colors</strong> (like HEX, RGBA, or HSL). It always has predictable lightness after color transformations (compared to HSL), it’s capable of encoding a wider range of colors, it offers native browser support, and unlike LCH and Lab, <strong>it has no hue shift</strong> when chroma is changed.”</p>
  </li>
  <li>
    <p><a href="https://keithjgrant.com/posts/2023/04/its-time-to-learn-oklch-color/">It’s Time to Learn oklch Color, by Keith J. Grant</a></p>

    <p>“In HSL, 100% saturation is simply as saturated as that particular color can be in the sRGB gamut. In OKLCH, the values aren’t based on technical limits or a mathematical definition, but rather on perceived equality. <strong>The amount of lightness indicates exactly how bright the color is</strong>, and the amount of chroma indicates exactly how vivid it is. The human eye perceives some colors like green or yellow to be brighter than others, like blue or purple, and OKLCH takes these details into account.”</p>
  </li>
</ul>

<p>The gist of it is that, similar to HSL, you can keep the Hue constant while adjusting the Lightness and Saturation (Chroma, in this case) independently. What sets OKLCH apart is that, unlike HSL and the others, all colors with the same hue <strong>actually look like they have the same hue</strong>! You know how making a vibrant blue lighter makes it look purple? Well, in OKLCH it still looks blue!</p>

<figure>
  <img src="/assets/blue-hue-difference-atmos.webp" alt="Difference between a blue color scale in LCH vs OKLCH" />
  <figcaption>Image from <a href="https://atmos.style/blog/lch-vs-oklch">atmos.style</a></figcaption>
</figure>

<p>You can also use <code class="language-plaintext highlighter-rouge">oklch(from…)</code> to convert HEX, RGB, etc. colors into OKLCH and <em>then</em> mess with their Lightness, Chroma, and Hue.</p>

<h2 id="what-i-did">What I did</h2>

<p>Firstly, I used the numbering format from the Tailwind color scales for familiarity.
Then I tried using <code class="language-plaintext highlighter-rouge">oklch(from…)</code> and adjusting the Alpha value to create a scale. But then colors on the scale could not be darker than the original. And if they ever overlap (think, text color with 80% opacity + background at 30%) then the color on top will be a mix of the two!</p>

<p>So I switched to using <code class="language-plaintext highlighter-rouge">calc()</code> instead of L and C values within <code class="language-plaintext highlighter-rouge">oklch()</code> and keeping the hue value the same.
I first created a color scale using an online generator, then converted to OKLCH and used a spreadsheet to calculate the difference between the Lightness and Chroma values of each color. I rounded those up and created variables in my CSS to represent the Lightness increment and the Chroma increment separately.</p>

<p><img src="/assets/color-scale-excel.webp" alt="" /></p>

<div class="language-scss highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">:root</span> <span class="p">{</span>

    <span class="cm">/* Base color */</span>
   <span class="na">--brand</span><span class="p">:</span> <span class="mh">#0d1bbd</span><span class="p">;</span>

    <span class="cm">/* Lightness and Chroma increments */</span>
    <span class="na">--l-increment</span><span class="p">:</span> <span class="m">0</span><span class="mi">.075</span><span class="p">;</span> <span class="cm">/* UP: Lighter*/</span>
    <span class="na">--c-increment</span><span class="p">:</span> <span class="m">0</span><span class="mi">.028</span><span class="p">;</span> <span class="cm">/* UP: LESS saturated*/</span>

    <span class="cm">/* Some of the resulting color tokens */</span>
    <span class="na">--bg-brand-50</span><span class="p">:</span> <span class="nf">oklch</span><span class="p">(</span><span class="n">from</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">brand</span><span class="p">)</span> <span class="nf">calc</span><span class="p">(</span><span class="n">l</span> <span class="o">+</span> <span class="nf">calc</span><span class="p">(</span><span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">l-increment</span><span class="p">)</span> <span class="o">*</span> <span class="m">8</span><span class="p">))</span> <span class="nf">calc</span><span class="p">(</span><span class="n">c</span> <span class="o">-</span> <span class="nf">calc</span><span class="p">(</span><span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">c-increment</span><span class="p">)</span> <span class="o">*</span> <span class="m">8</span><span class="p">))</span> <span class="n">h</span> <span class="o">/</span> <span class="m">1</span><span class="p">);</span>
    <span class="cm">/* … */</span>
    <span class="na">--bg-brand-800</span><span class="p">:</span> <span class="nf">oklch</span><span class="p">(</span><span class="n">from</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">brand</span><span class="p">)</span> <span class="n">l</span> <span class="n">c</span> <span class="n">h</span> <span class="o">/</span> <span class="m">1</span><span class="p">);</span> <span class="cm">/* This is the base color */</span>
    <span class="cm">/* … */</span>
    <span class="na">--bg-brand-950</span><span class="p">:</span> <span class="nf">oklch</span><span class="p">(</span><span class="n">from</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">brand</span><span class="p">)</span> <span class="nf">calc</span><span class="p">(</span><span class="n">l</span> <span class="o">-</span> <span class="nf">calc</span><span class="p">(</span><span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">l-increment</span><span class="p">)</span> <span class="o">*</span> <span class="m">2</span><span class="p">))</span> <span class="nf">calc</span><span class="p">(</span><span class="n">c</span> <span class="o">-</span> <span class="nf">calc</span><span class="p">(</span><span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">c-increment</span><span class="p">)</span> <span class="o">*</span> <span class="m">2</span><span class="p">))</span> <span class="n">h</span> <span class="o">/</span> <span class="m">1</span><span class="p">);</span>

<span class="p">}</span>
</code></pre></div></div>

<p>That seemed to work exactly how I imagined!</p>

<p>For that specific color…</p>

<h2 id="obstacles">Obstacles</h2>

<p>Obvious in hindsight: that method only works if the base colors all have similar Lightness and Chroma. There’s no way to create conditional statements (“if this, then that”) in CSS, so a base color would always have to occupy the same step on the color scale.</p>

<p>That can be sorted by spending a bit of extra time choosing base colors. Problem solved? Not so fast! Because of the way OKLCH works, some HEX/RGB/HSL colors do not have an OKLCH equivalent!</p>

<figure> 
    <img src="/assets/hsl-vs-oklch.webp" alt="Difference between a blue color scale in LCH vs OKLCH" /> 
    <figcaption>
        Image from <a href="https://evilmartians.com/chronicles/oklch-a-color-picker-made-to-help-think-perceptively">evilmartians.com</a>
    </figcaption> 
</figure>

<p><code class="language-plaintext highlighter-rouge">oklch(from…)</code> works by converting, say, a HEX value into OKLCH. But that means if you’re using HEX for your base variables, some colors are bound to look less saturated than the rest even if you max out their saturation in the HEX color space.</p>

<p><img src="/assets/color-scale-saturation.webp" alt="" /></p>

<h2 id="solution">Solution</h2>

<p>Switch to OKLCH for the base color variables. Then you can make sure the lightness and chroma of each color are the same, or close enough. Now, you do miss out on a couple of things when you do that…</p>

<ul>
  <li>You can’t just enter any color you like and get a color scale. You need to find its OKLCH Hue and input that instead. The original color might not even be part of the resulting color scale.</li>
  <li>Design tools like Figma do not support OKLCH, so you have to figure out the hue by other means.</li>
  <li>Code editors like VS Code don’t natively preview OKLCH colors like they do HEX, RGB, etc. You need to install an extension if you want that, but it can really slow down the app.</li>
</ul>

<p>But hey—it works! :D And changing a single number to get an entirely new color scale is kinda fun, like a design nerd’s slot machine. I figured this technique might be useful (and/or fun) to someone, so why not share.</p>

<p>Here’s the CSS you can use:</p>

<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">:root</span> <span class="p">{</span>

    <span class="c">/* Base colors */</span>
    <span class="c">/* Change the HUE (last number) for different colors. */</span>
    <span class="c">/* You might wanna change the Lightness and Chroma slightly too in some cases. */</span>
    <span class="py">--brand</span><span class="p">:</span> <span class="nf">oklch</span><span class="p">(</span><span class="m">0.40</span> <span class="m">0.30</span> <span class="m">265.71</span><span class="p">);</span>

    <span class="c">/* add more variables here */</span>

    <span class="c">/* Adjuts scales */</span>
    <span class="py">--l-increment</span><span class="p">:</span> <span class="m">0.075</span><span class="p">;</span> <span class="c">/* UP: Lighter*/</span>
    <span class="py">--c-increment</span><span class="p">:</span> <span class="m">0.028</span><span class="p">;</span> <span class="c">/* UP: LESS saturated*/</span>

    <span class="c">/* Color tokens */</span>
    <span class="c">/* Use them in classes like this: var(----bg-brand-600) */</span>
    <span class="py">--bg-brand-50</span><span class="p">:</span> <span class="nf">oklch</span><span class="p">(</span><span class="n">from</span> <span class="nf">var</span><span class="p">(</span><span class="l">--brand</span><span class="p">)</span> <span class="nf">calc</span><span class="p">(</span><span class="n">l</span> <span class="o">+</span> <span class="nf">calc</span><span class="p">(</span><span class="nf">var</span><span class="p">(</span><span class="l">--l-increment</span><span class="p">)</span> <span class="o">*</span> <span class="m">8</span><span class="p">))</span> <span class="nf">calc</span><span class="p">(</span><span class="n">c</span> <span class="o">-</span> <span class="nf">calc</span><span class="p">(</span><span class="nf">var</span><span class="p">(</span><span class="l">--c-increment</span><span class="p">)</span> <span class="o">*</span> <span class="m">8</span><span class="p">))</span> <span class="n">h</span> <span class="o">/</span> <span class="m">1</span><span class="p">);</span>
    <span class="py">--bg-brand-100</span><span class="p">:</span> <span class="nf">oklch</span><span class="p">(</span><span class="n">from</span> <span class="nf">var</span><span class="p">(</span><span class="l">--brand</span><span class="p">)</span> <span class="nf">calc</span><span class="p">(</span><span class="n">l</span> <span class="o">+</span> <span class="nf">calc</span><span class="p">(</span><span class="nf">var</span><span class="p">(</span><span class="l">--l-increment</span><span class="p">)</span> <span class="o">*</span> <span class="m">7</span><span class="p">))</span> <span class="nf">calc</span><span class="p">(</span><span class="n">c</span> <span class="o">-</span> <span class="nf">calc</span><span class="p">(</span><span class="nf">var</span><span class="p">(</span><span class="l">--c-increment</span><span class="p">)</span> <span class="o">*</span> <span class="m">7</span><span class="p">))</span> <span class="n">h</span> <span class="o">/</span> <span class="m">1</span><span class="p">);</span>
    <span class="py">--bg-brand-200</span><span class="p">:</span> <span class="nf">oklch</span><span class="p">(</span><span class="n">from</span> <span class="nf">var</span><span class="p">(</span><span class="l">--brand</span><span class="p">)</span> <span class="nf">calc</span><span class="p">(</span><span class="n">l</span> <span class="o">+</span> <span class="nf">calc</span><span class="p">(</span><span class="nf">var</span><span class="p">(</span><span class="l">--l-increment</span><span class="p">)</span> <span class="o">*</span> <span class="m">6</span><span class="p">))</span> <span class="nf">calc</span><span class="p">(</span><span class="n">c</span> <span class="o">-</span> <span class="nf">calc</span><span class="p">(</span><span class="nf">var</span><span class="p">(</span><span class="l">--c-increment</span><span class="p">)</span> <span class="o">*</span> <span class="m">6</span><span class="p">))</span> <span class="n">h</span> <span class="o">/</span> <span class="m">1</span><span class="p">);</span>
    <span class="py">--bg-brand-300</span><span class="p">:</span> <span class="nf">oklch</span><span class="p">(</span><span class="n">from</span> <span class="nf">var</span><span class="p">(</span><span class="l">--brand</span><span class="p">)</span> <span class="nf">calc</span><span class="p">(</span><span class="n">l</span> <span class="o">+</span> <span class="nf">calc</span><span class="p">(</span><span class="nf">var</span><span class="p">(</span><span class="l">--l-increment</span><span class="p">)</span> <span class="o">*</span> <span class="m">5</span><span class="p">))</span> <span class="nf">calc</span><span class="p">(</span><span class="n">c</span> <span class="o">-</span> <span class="nf">calc</span><span class="p">(</span><span class="nf">var</span><span class="p">(</span><span class="l">--c-increment</span><span class="p">)</span> <span class="o">*</span> <span class="m">5</span><span class="p">))</span> <span class="n">h</span> <span class="o">/</span> <span class="m">1</span><span class="p">);</span>
    <span class="py">--bg-brand-400</span><span class="p">:</span> <span class="nf">oklch</span><span class="p">(</span><span class="n">from</span> <span class="nf">var</span><span class="p">(</span><span class="l">--brand</span><span class="p">)</span> <span class="nf">calc</span><span class="p">(</span><span class="n">l</span> <span class="o">+</span> <span class="nf">calc</span><span class="p">(</span><span class="nf">var</span><span class="p">(</span><span class="l">--l-increment</span><span class="p">)</span> <span class="o">*</span> <span class="m">4</span><span class="p">))</span> <span class="nf">calc</span><span class="p">(</span><span class="n">c</span> <span class="o">-</span> <span class="nf">calc</span><span class="p">(</span><span class="nf">var</span><span class="p">(</span><span class="l">--c-increment</span><span class="p">)</span> <span class="o">*</span> <span class="m">4</span><span class="p">))</span> <span class="n">h</span> <span class="o">/</span> <span class="m">1</span><span class="p">);</span>
    <span class="py">--bg-brand-500</span><span class="p">:</span> <span class="nf">oklch</span><span class="p">(</span><span class="n">from</span> <span class="nf">var</span><span class="p">(</span><span class="l">--brand</span><span class="p">)</span> <span class="nf">calc</span><span class="p">(</span><span class="n">l</span> <span class="o">+</span> <span class="nf">calc</span><span class="p">(</span><span class="nf">var</span><span class="p">(</span><span class="l">--l-increment</span><span class="p">)</span> <span class="o">*</span> <span class="m">3</span><span class="p">))</span> <span class="nf">calc</span><span class="p">(</span><span class="n">c</span> <span class="o">-</span> <span class="nf">calc</span><span class="p">(</span><span class="nf">var</span><span class="p">(</span><span class="l">--c-increment</span><span class="p">)</span> <span class="o">*</span> <span class="m">3</span><span class="p">))</span> <span class="n">h</span> <span class="o">/</span> <span class="m">1</span><span class="p">);</span>
    <span class="py">--bg-brand-600</span><span class="p">:</span> <span class="nf">oklch</span><span class="p">(</span><span class="n">from</span> <span class="nf">var</span><span class="p">(</span><span class="l">--brand</span><span class="p">)</span> <span class="nf">calc</span><span class="p">(</span><span class="n">l</span> <span class="o">+</span> <span class="nf">calc</span><span class="p">(</span><span class="nf">var</span><span class="p">(</span><span class="l">--l-increment</span><span class="p">)</span> <span class="o">*</span> <span class="m">2</span><span class="p">))</span> <span class="nf">calc</span><span class="p">(</span><span class="n">c</span> <span class="o">-</span> <span class="nf">calc</span><span class="p">(</span><span class="nf">var</span><span class="p">(</span><span class="l">--c-increment</span><span class="p">)</span> <span class="o">*</span> <span class="m">2</span><span class="p">))</span> <span class="n">h</span> <span class="o">/</span> <span class="m">1</span><span class="p">);</span>
    <span class="py">--bg-brand-700</span><span class="p">:</span> <span class="nf">oklch</span><span class="p">(</span><span class="n">from</span> <span class="nf">var</span><span class="p">(</span><span class="l">--brand</span><span class="p">)</span> <span class="nf">calc</span><span class="p">(</span><span class="n">l</span> <span class="o">+</span> <span class="nf">calc</span><span class="p">(</span><span class="nf">var</span><span class="p">(</span><span class="l">--l-increment</span><span class="p">)</span> <span class="o">*</span> <span class="m">1</span><span class="p">))</span> <span class="nf">calc</span><span class="p">(</span><span class="n">c</span> <span class="o">-</span> <span class="nf">calc</span><span class="p">(</span><span class="nf">var</span><span class="p">(</span><span class="l">--c-increment</span><span class="p">)</span> <span class="o">*</span> <span class="m">1</span><span class="p">))</span> <span class="n">h</span> <span class="o">/</span> <span class="m">1</span><span class="p">);</span>
    <span class="py">--bg-brand-800</span><span class="p">:</span> <span class="nf">oklch</span><span class="p">(</span><span class="n">from</span> <span class="nf">var</span><span class="p">(</span><span class="l">--brand</span><span class="p">)</span> <span class="n">l</span> <span class="n">c</span> <span class="n">h</span> <span class="o">/</span> <span class="m">1</span><span class="p">);</span>
    <span class="py">--bg-brand-900</span><span class="p">:</span> <span class="nf">oklch</span><span class="p">(</span><span class="n">from</span> <span class="nf">var</span><span class="p">(</span><span class="l">--brand</span><span class="p">)</span> <span class="nf">calc</span><span class="p">(</span><span class="n">l</span> <span class="o">-</span> <span class="nf">calc</span><span class="p">(</span><span class="nf">var</span><span class="p">(</span><span class="l">--l-increment</span><span class="p">)</span> <span class="o">*</span> <span class="m">1</span><span class="p">))</span> <span class="nf">calc</span><span class="p">(</span><span class="n">c</span> <span class="o">-</span> <span class="nf">calc</span><span class="p">(</span><span class="nf">var</span><span class="p">(</span><span class="l">--c-increment</span><span class="p">)</span> <span class="o">*</span> <span class="m">1</span><span class="p">))</span> <span class="n">h</span> <span class="o">/</span> <span class="m">1</span><span class="p">);</span>
    <span class="py">--bg-brand-950</span><span class="p">:</span> <span class="nf">oklch</span><span class="p">(</span><span class="n">from</span> <span class="nf">var</span><span class="p">(</span><span class="l">--brand</span><span class="p">)</span> <span class="nf">calc</span><span class="p">(</span><span class="n">l</span> <span class="o">-</span> <span class="nf">calc</span><span class="p">(</span><span class="nf">var</span><span class="p">(</span><span class="l">--l-increment</span><span class="p">)</span> <span class="o">*</span> <span class="m">2</span><span class="p">))</span> <span class="nf">calc</span><span class="p">(</span><span class="n">c</span> <span class="o">-</span> <span class="nf">calc</span><span class="p">(</span><span class="nf">var</span><span class="p">(</span><span class="l">--c-increment</span><span class="p">)</span> <span class="o">*</span> <span class="m">2</span><span class="p">))</span> <span class="n">h</span> <span class="o">/</span> <span class="m">1</span><span class="p">);</span>

<span class="p">}</span>
</code></pre></div></div>

<hr />

<h2 id="disclosure">Disclosure</h2>
<p>I originally planned to name this post “What I learned making an OKLCH color scale generator in CSS” and it was gonna have a section titled “Why it failed”. While writing that I realized… I had not failed. I just needed to tweak some Chroma values (and mention some caveats)! ;)</p>

<h3 id="special-thanks">Special thanks…</h3>
<p>…to <a href="https://github.com/dragos-efy/efy">Dragos</a> for nagging me about how cool OKLCH is for months, until I checked it out. 😁</p>]]></content><author><name></name></author><category term="code" /><summary type="html"><![CDATA[]]></summary></entry></feed>