<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://sull1van.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://sull1van.com/" rel="alternate" type="text/html" /><updated>2026-07-10T12:35:50+00:00</updated><id>https://sull1van.com/feed.xml</id><title type="html">Sean Sullivan</title><subtitle>Personal blog on technology, engineering, health projects</subtitle><author><name>Sean Sullivan</name></author><entry><title type="html">Thoughts on a Year Sober</title><link href="https://sull1van.com/thoughts-on-a-year-sober.html" rel="alternate" type="text/html" title="Thoughts on a Year Sober" /><published>2026-07-04T00:00:00+00:00</published><updated>2026-07-04T00:00:00+00:00</updated><id>https://sull1van.com/thoughts-on-a-year-sober</id><content type="html" xml:base="https://sull1van.com/thoughts-on-a-year-sober.html"><![CDATA[<p><br />
Today marks one full year since I went sober. <br />
One year!
<br /><br /></p>

<h3 id="background">Background</h3>

<p>I had toyed with the idea of going sober ever since the middle of college. Everyone has different relationships with substances, and mine with alcohol always felt like it should be temporary. As I got older and graduated, it felt like time to move on, and that anything more than a nice buzz should stay back in college. But month after month, I kept having nights where I got more drunk than intended, and I hated it. I could always control whether I drank — I had plenty of totally sober stretches in college — but when I drank, I was never the guy who could have one or two and stop (The em dashes were me, not ai). That’s what I hope would have changed by now. I also just hated how I acted when I was drunk.</p>

<p>My path to sobriety didn’t really take off until I got some concerning blood tests back in early 2025. The tests showed significant elevation in my ALT and AST, key liver enzymes used to detect liver stress and damage. My doctor mentioned that I should probably slow down on drinking if that’s what I had been up to, but that he didn’t think I had any kind of liver disease. But after seeing the results, and being more embarrassed than anything, I realized it was obvious what needed to change. I started to take my health much more seriously. I started to supplement with various things to help out my liver, eventually creating <a href="https://sull1van.com/best-liver-of-all-time">my own supplement stack</a> for it.</p>

<details class="note-card">
  <summary>FOOTNOTE ON Other Projects</summary>
  <div class="note-card-body">
    <div class="note-card-body-inner">
      <p>Later on into sobriety, I also built <a href="https://sull1van.com/tracking-blood-tests">a web dashboard</a> to track my blood test results so I could watch them more closely. But at this point I hadn't built it yet.</p>
    </div>
  </div>
</details>

<p><br /></p>

<p>These things did help, and they pushed me to really <em>want</em> to use moderation and to drink less. But weekend after weekend, I just couldn’t have one drink and call it a night. I wouldn’t even blame peer pressure, it was just that I never set a good boundary for myself. So, one morning that summer, I woke up and decided to cut it off entirely. Time to go sober.
<br /></p>

<p><br /></p>

<h3 id="rules-of-my-sobriety">Rules of my sobriety</h3>

<p>Sobriety felt pretty scary at first. For the first few days I was terrified I’d give in, constantly thinking, <em>“What if I drink again? What if I mess up?”</em>  I couldn’t even picture a long-term goal, only that I had to make it for two months.</p>

<p>But as the weeks went by, I started to get less scared. With each day in those first two months, I started to collect evidence that I could live my life and not drink. It started to feel more good than scary.</p>

<p>I started to settle in to things, thinking about them more practically. At first I had no idea what was in the bounds of sobriety versus out, so I banned alcohol of any kind. Mouthwash, even. Sobriety is less simple than it sounds, and there are a lot of technicalities. What about a “non-alcoholic” beer that actually has 0.1% or 0.5% alcohol? I would have to drink ~40 of those to equal one beer, but it’s still alcohol, right?</p>

<p>At first I was really strict about all this, but after a while, I realized that a single drop of alcohol in the NA beer was never the thing I was trying to escape. I was just trying to stop getting drunk. So I made new rules:</p>
<ol>
  <li>If it’s labeled “NA” (0.5% alcohol or less), I could drink it.</li>
  <li>If something was classified as alcoholic, so &gt;0.5%, it counted as breaking sobriety if I swallowed it.</li>
</ol>

<p>That meant the trace alcohol from an NA beer was fine, and any kind of mouthwash or other alcohol was also fine if I rinsed out afterward. You might say these are permissive rules, and that’s fair, they worked for me. I was never in the territory of life-or-death alcoholism, so I didn’t feel like my sobriety needed to be that strict. I stuck to these rules for the entire year, so it was really important that they at least be manageable ones (Also, it feels both weird and pretty cool to say that I did that).</p>

<p>Another point of my sobriety was that it actually became threefold. I wanted it to feel like a real personal reset, so I brought in <strong>smoking (weed) and vaping too, not just drinking</strong>. 
Plenty of people don’t do these things to begin with, so I don’t think I’m “special” in any way, I just wanted to make it a little more challenging and remove the chance I’d replace one substance with another.</p>

<p><br /></p>
<h3 id="just-go-longer">Just go longer</h3>

<p>While my sobriety was threefold, it was only alcohol that made me afraid of relapse. Like I said, I told myself I was sober <em>for now</em>, not forever. I told everyone that I was doing it for two months, just to see where things went. I didn’t commit to going longer until I knew I could.</p>

<p>Cravings are like that. At first, they seem impossible to get rid of, but they fall off fast and don’t really come back. As I neared the halfway point of those two months, the daily panic about when I would drink next faded away, replaced by thoughts that felt more normal. It was around that time that I caught up with an old friend, who gave me what turned out being the single most important piece of advice I’d heard all year.</p>

<p>We got into chatting, and I explained my sobriety to him as well as the two-month goal. He had been sober for a pretty long time, so I imagine this didn’t sound like anything crazy. He asked why I settled on two months.</p>

<p>I don’t know, I told him. I just assumed that I’d be giving in at two months and wouldn’t be able to keep this going. I didn’t really want it to end in two months, I told him, but that I assumed it would.</p>

<p><em>“Why don’t you just go longer?”</em></p>

<p>I stared at him for a second. It never even occurred to me that I could just plan for longer.</p>

<p>But yeah, I could. Just go longer. So that’s exactly what I did. At the end of the two months I decided to keep going. Two months turned into six, and then at six months I said twelve. Now here we are, twelve months later. It’s crazy.</p>

<p><br />
<br /></p>
<h3 id="changes-i-noticed">Changes I noticed</h3>

<p>The changes in my body showed up fast, within 3 months. I noticed increased energy during the day and whiter eyes, which was a surprisingly great combo. I also worked on my general health and refined that supplement stack I mentioned. Around the same time as this, my cravings evaporated. By month three I no longer had any big urge to drink. I’d settled into the reality that I would just go to the bar with friends, sit my ass down, and order a soda or an NA beer. The lack of alcohol didn’t really manifest as a craving anymore, more like it was just a routine I had to follow. Get the NA option, nothing else.</p>

<details class="note-card">
  <summary>FOOTNOTE ON N.A. BEERS</summary>
  <div class="note-card-body">
    <div class="note-card-body-inner">
      <p>And on that note, NA beers are awesome. They're not for everyone, but a ton of stores and bars have started stocking them in this last year. It definitely beats a soda if you're doing something social and want a drink in your hand. Also, if you aren't a beer person, NA beers might make you one after you go sober, lol</p>
    </div>
  </div>
</details>
<p><br /></p>

<p>Between the six-month to one-year period, the changes were more gradual, but these biomarkers trended to the best levels I’ve ever tested for:</p>
<ul>
  <li>ALT</li>
  <li>AST</li>
  <li>HDL Cholesterol</li>
  <li>LDL Cholesterol</li>
  <li>Fasted Glucose</li>
  <li>Hemoglobin A1c</li>
</ul>

<p>This was a really big accomplishment for me, since some of these were pretty high to begin with. I’m happy to say that, as of 2026, I have never had a better-functioning liver in my life, and that’s saying a lot since I have been getting these tests since I was <strong>seventeen</strong>!
<br />
<br />
<br /></p>

<h3 id="what-i-still-miss">What I still miss</h3>
<p>I don’t miss being drunk. I actually saw that coming before I quit, as I could feel the hangovers kicking in before I would even get back home from a night out. Heavy drinking had already lost its appeal, which is why I had been slowly cutting the number of nights I drank per month. I don’t really miss that.</p>

<p>But something I <em>do</em> miss is that nice buzz you get after one, maybe two drinks. The state where you have a slightly elevated mood, and things seem a little more fun and playful. And that’s still where my head is today. The moments of drinking that I miss are pretty specific and infrequent. You’re at someone’s house, out on a date, at a birthday dinner, and one drink would be perfect to soften the mood. Without it, social stuff takes on a slightly different feeling. Not worse, but just a little different. Not drinking is fine, I’ll live, but I would like to experience alcohol again in moderation.</p>

<p>Drinking is also just part of culture here in the Midwest. We don’t have as much of the great outdoors as other regions, and we get some pretty bad winters, so a lot of times this is how we bond. Going sober made it pretty obvious to me that alcohol is ingrained into how people connect out here.</p>

<p><br />
<br /></p>

<h3 id="would-i-recommend-you-do-this">Would I recommend you do this?</h3>
<p>People have asked me this, and I would recommend it! But I think you should do what’s right for you. Sobriety is awesome, but there’s something to be said for having the ability to use alcohol on occasion, to treat a drink the way you might have a sweet treat to celebrate a milestone. Or even to treat it like caffeine: you should be able to have a three-coffee day once in a while if that’s what you want. For people who can participate in this kind of thing responsibly, I would say to take advantage where you can.</p>

<p>In an ideal world, that’s how it would work. You’d use what you want in moderation, feel a specific way, and stop if you notice negative effects. But the last part takes a lot of introspection and honest self-assessment, and I don’t think it always plays out that way in real life. So for that reason, if you have issues with moderating your drinking, and you want to do <em>something</em>, there are tons of things you can try, from therapies to supplements and medications. And if you want resources for different things you can try, or different things that I’ve tried, I’m here for you. And if you want something more drastic, and you <em>want</em> to go sober full-stop, then yes, go for it! But if you don’t have a problem and you’re just asking whether you should go sober, I’d say you may get more satisfaction out of holding yourself to one or two drinks a night. Just start trying things and see what works!</p>

<details class="note-card">
  <summary>FOOTNOTE ON WHAT I LEARNED ABOUT PEOPLE</summary>
  <div class="note-card-body">
    <div class="note-card-body-inner">
      <p>People have been really supportive of me for the most part. I've had tons of questions about my sobriety, and it's most often a nice conversation. </p>
      <p>But what I also get sometimes (very rarely though) is a look of guilt. Sometimes, other people almost seemed upset that I wasn't drinking when they were. Or maybe just judgement that someone is going against what most people do. I get it, though. It would be like going out for a friend's birthday and bringing your own food because you're on a meal plan. It just breaks social norms and confuses people, since it's the opposite of what the vast majority do. The alternative for us, who are doing these things, would be to stay home and skip social events, which is a terrible alternative.</p><br />
      <p>And while not necessarily specific to me, I have also noticed a lot of judgement over people who are trying to better themselves by using uncommon means (anything that the majority isn't doing), not just by going fully sober. I don't think most people get how common addiction actually is, alcohol or otherwise, and how many people are fighting it daily. The problem with not realizing how common this is, is that people will judge someone without knowing what's going on, often times shaming them for the thing that's getting them out of the addiction. </p>
      <p>For instance, I tried naltrexone for a while. It's a drug usually reserved for people with a diagnosed alcohol use disorder, but my doctor said it was totally fine for me to try on weekends. But if it got casually brought up to an acquaintance that I was taking a drug alcoholics use, and they didn't know everything I just told you here, they might judge me for it. I think it could be similar to when someone with food addiction takes a GLP to kill their cravings. Their goal might be to simply stop the urge to constantly shove calories into their body. But I think people might judge them based on what they are doing, without knowing the context. </p><p>So my hope is that over time, people can become a little more respectful of others situations.</p>
    </div>
  </div>
</details>

<p><br /></p>

<h3 id="will-i-stay-sober-past-one-year">Will I stay sober past one year?</h3>
<p>I’m not sure yet. For me, it was about getting healthier and getting rid of my craving to drink. A year later, I’ve achieved a lot of what i was hoping for. I want to keep this same relationship with alcohol going forward, but <em>with</em> the ability to have a drink if I want one.</p>

<p>It’s also been incredible to see how much I got done with all the weekends I wasn’t going out. I refined my <a href="https://sull1van.com/7500-miles-self-driving-car">self-driving car project</a>. I honed my health and got the <a href="https://sull1van.com/best-liver-of-all-time">best blood test results</a> of my entire life. I worked on a passion project that <a href="https://sull1van.com/a-dozen-chargers-in-the-lab">graded two dozen phone chargers</a>, continuing a Google engineer’s work. I created a half-dozen AI-assisted vibe coding projects, replacing stuff like my Spotify and my workout app with custom-coded alternatives that are 100% free to operate (article coming soon). A lot of stuff.</p>

<p>I plan to return to drinking casually one day. Maybe not just yet, but one day. And if I still can’t do the 1-2 drinks a night thing, I’ve got a year’s worth of sobriety showing me I can always do it again.</p>

<p><br />
<br /></p>]]></content><author><name>Sean Sullivan</name></author><category term="meta" /><category term="blogging" /><summary type="html"><![CDATA[Today marks one full year since I went sober. One year!]]></summary></entry><entry><title type="html">[PROJECT] B.L.O.A.T: Getting the best liver of all time</title><link href="https://sull1van.com/Best-liver-of-all-time.html" rel="alternate" type="text/html" title="[PROJECT] B.L.O.A.T: Getting the best liver of all time" /><published>2026-05-19T00:00:00+00:00</published><updated>2026-05-19T00:00:00+00:00</updated><id>https://sull1van.com/Best-liver-of-all-time</id><content type="html" xml:base="https://sull1van.com/Best-liver-of-all-time.html"><![CDATA[<p>Earlier in 2025, I did bloodwork for the first time in a while, and found I had some insanely high liver enzymes. I’d come off the heels of five years of college, having spent the last ~year and a half drinking like my liver was bulletproof. I realized that something needed to change, and spent the next year of my life committed to achieving the healthiest liver possible. Turns out, if you take care of your liver, it most definitely will take care of you too.</p>

<div class="post-toc post-toc--glass">
  <div class="post-toc-title">Table of Contents</div>
  <ul>
    <li><a href="#the-baseline">The baseline</a></li>
    <li><a href="#step-one-research">Step one: research</a></li>
    <li class="nested"><a href="#the-glutathione-rabbit-hole">The glutathione rabbit hole</a></li>
    <li><a href="#step-two-stop-drinking">Step two: stop drinking</a></li>
    <li><a href="#the-stack">The stack</a></li>
    <li><a href="#going-one-step-further">Going one step further</a></li>
    <li><a href="#the-rematch">The rematch</a></li>
    <li><a href="#what-i-think-worked">What I think worked</a></li>
    <li><a href="#the-verdict">The verdict</a></li>
    <li><a href="#sources-i-used">Sources I used</a></li>
  </ul>
</div>

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

<p>I mentioned at the beginning that this all started because of some bad blood test results. But which ones specifically? The main markers came from a Comprehensive Metabolic Panel, something that I used to call this a liver panel, but realized isn’t quite right. A CMP covers more than the liver, so I filter it down to the values I care about:</p>

<ul>
  <li>Total protein</li>
  <li>Albumin</li>
  <li>Globulin</li>
  <li>Albumin/globulin ratio</li>
  <li>Total bilirubin</li>
  <li>Alkaline phosphatase</li>
  <li>AST</li>
  <li>ALT</li>
</ul>

<p>ALT and AST are the big ones for me because they are the main liver stress enzymes [<a href="#ref-0" class="cite-link">0</a>]. They don’t tell the whole story of liver function, but if you have been drinking and those numbers are high, they get your attention pretty quickly.</p>

<p>Albumin, total protein, globulin, and A/G ratio tell more of the surrounding story, helping to explain things like immune activity and whether the body is keeping its basic chemistry in a good place. (I sound like I know what I’m talking about, but most of this is from Google). Bilirubin and alkaline phosphatase are worth watching too, though bilirubin can bounce around for reasons that do not automatically worry me, and alkaline phosphatase is not purely a liver marker.</p>

<p>So while ALT and AST are my focus, the whole picture has to look good.</p>

<p>Now even inside of a normal range, the individual value is still important. After some research, I came across these generalized ‘trends’ for what makes something more optimal, even if it’s the normal range. 
Holding all else equal, if we are within the normal range, here’s what you want for each marker in a liver panel:</p>
<ul>
  <li>Albumin: Higher is better</li>
  <li>A/G Ratio: Higher is better</li>
  <li>Total Protein: Higher is better</li>
  <li>Globulin: Dead middle is better</li>
  <li>ALT: Lower is better</li>
  <li>AST: Lower is better</li>
  <li>Alkaline Phosphatase: Lower is better</li>
  <li>Bilirubin: Makes no difference</li>
</ul>

<p>This provides a way to differentiate test results that are close but still considered ‘within the normal range’. So if I’m comparing two test results that are within the normal range, clinically they may both be considered the same, but biologically one of them might be just slightly better.</p>

<p>One really cool piece of context to this is that I’ve been getting blood tests since I was seventeen. That is useful because I have my own younger-me data, which is more useful than a generic ‘normal range’ for these test results. I can look at what my numbers were before I spent a few years making worse decisions.</p>

<p>Now, here was seventeen-year-old me when he got his CMP:</p>

<table class="bloat-table">
  <thead>
    <tr>
      <th>Analyte</th>
      <th>2018 report, age 17</th>
    </tr>
  </thead>
  <tbody>
    <tr><td>Total protein</td><td>7.1 g/dL</td></tr>
    <tr><td>Albumin</td><td>4.7 g/dL</td></tr>
    <tr><td>Globulin</td><td>2.4 g/dL</td></tr>
    <tr><td>A/G ratio</td><td>2.0</td></tr>
    <tr><td>Total bilirubin</td><td>0.7 mg/dL</td></tr>
    <tr><td>Alkaline phosphatase</td><td>90 U/L</td></tr>
    <tr><td>AST</td><td>28 U/L</td></tr>
    <tr><td>ALT</td><td>17 U/L</td></tr>
  </tbody>
</table>

<p>Pretty good, honestly.</p>

<p>Then there was twenty-four-year-old me:</p>

<table class="bloat-table">
  <thead>
    <tr>
      <th>Analyte</th>
      <th>2025 report, age 24</th>
      <th>Change from 2018</th>
    </tr>
  </thead>
  <tbody>
    <tr><td>Total protein</td><td>6.7 g/dL</td><td class="diff-neg">Decrease by 0.4</td></tr>
    <tr><td>Albumin</td><td>4.4 g/dL</td><td class="diff-neg">Decrease by 0.3</td></tr>
    <tr><td>Globulin</td><td>2.3 g/dL</td><td class="diff-neg">Decrease by 0.1</td></tr>
    <tr><td>A/G ratio</td><td>1.9</td><td class="diff-neg">Decrease by 0.1</td></tr>
    <tr><td>Total bilirubin</td><td>0.7 mg/dL</td><td class="diff-neutral">No change</td></tr>
    <tr><td>Alkaline phosphatase</td><td>54 U/L</td><td class="diff-pos">Decrease by 36</td></tr>
    <tr><td>AST</td><td>147 U/L</td><td class="diff-neg">Increase by 119</td></tr>
    <tr><td>ALT</td><td>71 U/L</td><td class="diff-neg">Increase by 54</td></tr>
  </tbody>
</table>

<p>Yikes lol.</p>

<p>While my liver was still functioning generally well at the time of this test, the enzymes were extremely worrisome. As I mentioned before, this was taken after I graduated college. I spent nearly the entire calendar year at a bar, from Summer 2023 to Fall 2024. It was interesting since I had drank little in 2025 (at the time this test was done), but I stopped <em>because</em> the hangovers were getting too bad. So I knew any bad results this many months later were a sign of latent liver injury. And keep in mind, I was still drinking, just less frequently due to those hangovers.</p>

<p><strong>Needless to say, after getting this test, I was motivated to finally take charge of my liver health.</strong></p>

<h2 id="step-one-research">Step one: research</h2>
<h4 id="the-glutathione-rabbit-hole">The glutathione rabbit hole</h4>

<p>I started to research more about glutathione, a supplement that could potentially help regenerate my liver. Funny enough, I had actually dealt with it before. Back in 2022, I went to a men’s clinic after my friend convinced me to get my blood tested like him. To optimize as many biomarkers as possible. Their main finding was that my liver was stressed with slightly elevated enzymes, and that I could inject glutathione if I wanted to. They put me on 400mg weekly.</p>

<p>The injections were really painful. It has to go straight into muscle, and it’s slightly acidic, so it stings while it goes in. I don’t have any hard data on whether those few injections did anything, but my liver was mostly normal at the time anyway. I ended up stopping it and forgetting about glutathione.</p>

<p>When I came back to it in 2025, I had one basic question: can I take this orally and avoid stabbing myself?</p>

<p>As I learned, plain glutathione has a bioavailability problem. One newer paper on glutathione analogues says native oral glutathione has bioavailability of &lt;1% because it gets broken down enzymatically and does not absorb well through the gut [<a href="#ref-1" class="cite-link">1</a>]. That same paper tested modified versions of glutathione and found that one ‘N-methylated’ analog had much better half-life and oral bioavailability than native glutathione. Sounds promising, but I have no idea where someone would go to buy that.</p>

<p>The more practical thing I found was S-acetyl L-glutathione, usually shortened to SAG.
It’s basically a modified glutathione molecule, forced onto an acetyl group that <em>supposedly</em> makes it more stable and helps it get into cells. This was probably the best oral composition out there.</p>

<p>The best human data I found was a small 2018 crossover study in eighteen healthy volunteers. It compared a single large oral dose of S-acetyl glutathione against regular glutathione. The study found higher plasma GSH Cmax and AUC after SAG than after the regular glutathione product, although some of the other results were messier and actually favored regular glutathione on some measures. Definitely not a slam dunk, but it was enough to make SAG look more plausible [<a href="#ref-2" class="cite-link">2</a>].</p>

<p>There was also a 2025 safety assessment in <em>Food and Chemical Toxicology</em> that looked at SAG for use in foods and dietary supplements. The summary I found reported no genotoxic signal, an acute oral LD50 above 2000 mg/kg in rats, and a 13-week rat NOAEL of 1500 mg/kg/day. That does not prove anything magical about how it absorbs, but it did make the safety profile look decent [<a href="#ref-3" class="cite-link">3</a>].</p>

<p>At that point, my conclusion was pretty simple: oral glutathione itself is probably not the move, but S-acetyl glutathione is at least interesting enough to try.</p>

<h2 id="step-two-stop-drinking">Step two: stop drinking</h2>
<p>While the supplements helped, blood tests from the month afterward showed only moderate improvement. My liver enzymes were still elevated. The smart move was easy to understand but hard to do. I needed to stop drinking.</p>

<p>It was about three months of experimenting with supplementation before I fully accepted that I was not going to fix my liver while giving it the same thing that caused the problem. I had already been thinking about going sober for a while, so the bloodwork made that decision feel easier to make. It went from “maybe this would be a good reset” to “I don’t think my liver will go back to normal if I don’t do this”.</p>

<p>I made the decision to stop drinking. It was about 3.5 months after that first concerning blood test. 
My liver continued to improve in the months afterward, but the enzymes were still nothing incredible.</p>

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

<p>After three months sober, and 6.5 months into my journey of committing to improve my liver, I created a supplement stack around glutathione support and general inflammation. This is what I settled on:</p>

<ul>
  <li>S-acetyl-L-glutathione, 200 mg per day</li>
  <li>NAC, 600 mg per day</li>
  <li>TMG, 4 g per day</li>
  <li>Turmeric, 1 g per day</li>
  <li>Grape seed extract</li>
  <li>Fish oil, specifically Nordic Naturals Complete Omega Xtra</li>
  <li>Elderberry extract, 500 mg per day</li>
</ul>

<p>The liver part was mostly SAG plus NAC. NAC is a precursor for glutathione synthesis [<a href="#ref-7" class="cite-link">7</a>], and SAG was my attempt to get pure glutathione into my body without injections. TMG was there because I was interested in gains at the gym, and high doses of TMG are known for helping muscle growth [<a href="#ref-8" class="cite-link">8</a>]. Fish oil and turmeric were there for inflammation, and elderberry is more of a general-purpose antiviral I take to stay healthy.</p>

<p>Was this perfectly controlled science? NOPE! But I was going to do it all anyway and see what happened.</p>

<p>At this point, I had changed a bunch of these things at once: no alcohol, better diet, supplements, more health tracking, and a level of motivation I do not usually have.</p>

<p><em>To be fair: I started the supplements <strong>seven months</strong> after I stopped drinking, and my data show that my ALT and AST levels dropped to just-above normal levels when I started supplementation. With drinking, it’s usually understood that the liver completes its recovery in a few short months. For this reason, I’m inclined to believe that the supplements were the thing pushing me over the edge here, and into B.L.O.A.T. territory.</em></p>

<p>After running the stack for about three months, my numbers came back into the normal range. Nice! My ALT and AST were finally ‘normal’. They were at the higher end of normal, but still normal.</p>

<p>The problem was that <strong>normal</strong> was only my first goal. B.L.O.A.T. was still out there.</p>

<h2 id="going-one-step-further">Going one step further</h2>

<p>Once the oral stack got me back into a safer place, I doubled down on beating my old best test results.</p>

<p>I started by bringing back injectable glutathione. I went back to the exact same men’s clinic that I had visited years ago, paid to see a physician, and explained to her everything I’ve just shown you. While she thought I was a little obsessed over it, she said it couldn’t hurt to try. We settled on 600 mg weekly, slightly more than my OG prescription years ago. It was still painful, and still sucked to do every week, but it was just for a few weeks. I was doing this to give my liver a short-term boost to help it regenerate [<a href="#ref-6" class="cite-link">6</a>].</p>

<p>This was the differentiator. A short few weeks later, May 2026 came around.</p>

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

<p>Here is the oldest test against the newest test, complete with the trends we talked about before:</p>

<style>
  .cite-link { color: #0000EE !important; text-decoration: underline !important; }
  .cite-link:visited { color: #551A8B !important; }
  .ref-marker { color: #0000EE !important; text-decoration: underline !important; }
  .ref-marker:visited { color: #551A8B !important; }
  .bloat-table {
    border-collapse: collapse;
    width: auto;
    margin: 0 auto;
    font-family: sans-serif;
    font-size: calc(1em - 1px);
  }
  .bloat-table th, .bloat-table td {
    border: 1px solid var(--table-cell-border);
    text-align: left;
    padding: 6px 10px;
  }
  .bloat-table th {
    background-color: var(--table-head-bg);
  }
</style>

<div class="table-wrapper">
<table class="bloat-table">
  <thead>
    <tr>
      <th>Analyte</th>
      <th>2018 report, age 17</th>
      <th>2026 report, age 25</th>
      <th>My Opinion</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Total protein</td>
      <td>7.1 g/dL</td>
      <td class="diff-pos">7.2 g/dL</td>
      <td class="diff-pos">Better</td>
    </tr>
    <tr>
      <td>Albumin</td>
      <td>4.7 g/dL</td>
      <td class="diff-pos">4.7 g/dL</td>
      <td class="diff-pos">Equal</td>
    </tr>
    <tr>
      <td>Globulin</td>
      <td>2.4 g/dL</td>
      <td class="diff-pos">2.5 g/dL</td>
      <td class="diff-pos">Better (2.7 is technical best)</td>
    </tr>
    <tr>
      <td>A/G ratio</td>
      <td>2.0</td>
      <td class="diff-neg">1.9</td>
      <td>Worse (barely)</td>
    </tr>
    <tr>
      <td>Total bilirubin</td>
      <td>0.7 mg/dL</td>
      <td>1.0 mg/dL</td>
      <td>Doesn't matter</td>
    </tr>
    <tr>
      <td>Alkaline phosphatase</td>
      <td>90 U/L</td>
      <td class="diff-pos">79 U/L</td>
      <td class="diff-pos">Better</td>
    </tr>
    <tr>
      <td>AST</td>
      <td>28 U/L</td>
      <td class="diff-pos">25 U/L</td>
      <td class="diff-pos">Better.</td>
    </tr>
    <tr>
      <td>ALT</td>
      <td>17 U/L</td>
      <td class="diff-pos">17 U/L</td>
      <td class="diff-pos">Equal</td>
    </tr>
  </tbody>
</table>
</div>

<p>I started chuckling at the new result. 2026 wins.</p>

<p>I know that not <em>every</em> single marker was better in 2026, but most were. A/G ratio was slightly worse, bilirubin rose a little, so if I were trying to fight against myself, there are places to do it. But if you look at the liver enzymes, they are ridiculous now. AST dropped from 147 to 25. ALT dropped from 71 to 17. Even compared with my seventeen-year-old baseline, AST is better and ALT is the same. That is insane to me.</p>

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

<p>If I had to rank the interventions, sobriety and glutathione tie for the top spot.</p>

<p>Sobriety is important because you can’t really expect your liver to heal if you are continually bombarding it with stress. Cutting alcohol created the perfect space for my liver to regenerate itself, and I’d recommend anyone do the same if they are in a similar situation.</p>

<p>However, I do think there is a lot to say about injectable glutathione. Injectable glutathione had the clearest impact on my liver enzymes by far. I want to slightly push back on the notion that sobriety is the #1 thing that is going to help someone’s liver get to its best functioning state of all time. While avoiding heavy drinking is an absolute must, my data showed that it only led to modest improvements. To actually get to best-functioning territory, the injectable glutathione pushed me over the edge. Take a look at the timeline of my biomarkers below. If sobriety <em>really</em> was the main thing driving this, we would have seen remarkable improvement in these enzymes. We didn’t. The most dramatic drop was actually not the time when I went sober, but <strong>the time that I started doing intramuscular glutathione</strong>. Keep in mind this was only for about 6 weeks. I think this is as good a testimonial as any, that these interventions do work.</p>

<div class="post-gallery">
  <!-- Row 1: screen1 & screen2 + caption -->
  <div class="post-gallery-row post-gallery-row--2-1">
    <div class="post-gallery-images">
      <img src="/assets/images/2026-05-19-Best-liver-of-all-time/BLOAT_ALT.jpg" alt="ALT Levels" class="post-gallery-img" />
      <img src="/assets/images/2026-05-19-Best-liver-of-all-time/BLOAT_AST.jpg" alt="AST Levels" class="post-gallery-img" />
    </div>
    <div class="post-gallery-caption">
      With ALT especially, it's clear that the most significant drop in enzymes occurred when I was using intramuscular glutathione. The original drop from March 2025 onward was after 3 months of sobriety + 6 months of supplementation.

      Also - this is my new blood test tracking app, developed as yet another side project. You can read about it [here](https://sull1van.com/tracking-blood-tests) if interested.
    </div>
  </div>
</div>

<p>As far as the supplements go, I don’t think any oral supplement is going to outsmart alcohol if heavy alcohol consumption is the main thing stressing your liver. But I do think oral supplements help, such as the SAG and grape seed extract. The research is promising [<a href="#ref-4" class="cite-link">4</a>][<a href="#ref-5" class="cite-link">5</a>], and my test results add more fuel to that fire. S-Acetyl-L-Glutathione is the only one I’d take orally. And after injecting pure glutathione, I learned that it costs only a little more than the supplement anyway. So for anyone who is considering one of the two, I’d say do whatever you are most comfortable with, but know that both will probably help you out in some capacity.</p>

<h2 id="and-thats-it">And that’s it</h2>

<p>I started with a simple goal: get my liver back into range.</p>

<p>Then, because I was mad at myself for letting it fall out of range, I turned it into a competition against my own teenage bloodwork. And take that, teenage me! Twenty-five year old me is just as good, if not better.</p>

<p>As of May 2026, I have the best liver test results of my life. Maybe not every single marker, if you want to pick at it. But taken as a full picture, especially with AST and ALT, this is the best my liver has ever looked on paper.</p>

<p>B.L.O.A.T. achieved.</p>

<h2 id="references">References</h2>

<p id="ref-0"><a href="https://www.ncbi.nlm.nih.gov/books/NBK482489/" class="ref-marker">[0]</a> Liver Function Tests: <a href="https://www.ncbi.nlm.nih.gov/books/NBK482489/">https://www.ncbi.nlm.nih.gov/books/NBK482489/</a></p>
<p id="ref-1"><a href="https://pubmed.ncbi.nlm.nih.gov/40143049/" class="ref-marker">[1]</a> Enhancing the Oral Bioavailability of Glutathione Using Innovative Analogue Approaches: <a href="https://pubmed.ncbi.nlm.nih.gov/40143049/">https://pubmed.ncbi.nlm.nih.gov/40143049/</a></p>
<p id="ref-2"><a href="https://www.graphyonline.com/archives/IJCND/2018/IJCND-134/" class="ref-marker">[2]</a> Oral Administration of S-acetyl-glutathione: Impact on the Levels of Glutathione in Plasma and in Erythrocytes of Healthy Volunteers: <a href="https://www.graphyonline.com/archives/IJCND/2018/IJCND-134/">https://www.graphyonline.com/archives/IJCND/2018/IJCND-134/</a></p>
<p id="ref-3"><a href="https://www.sciencedirect.com/science/article/pii/S0278691525000468" class="ref-marker">[3]</a> Safety assessment of S-Acetyl Glutathione for use in foods and dietary supplements: <a href="https://www.sciencedirect.com/science/article/pii/S0278691525000468">https://www.sciencedirect.com/science/article/pii/S0278691525000468/</a></p>
<p id="ref-4"><a href="https://pmc.ncbi.nlm.nih.gov/articles/PMC3003214/" class="ref-marker">[4]</a> Grape Seed Extract to Improve Liver Function in Patients with Nonalcoholic Fatty Liver Change: <a href="https://pmc.ncbi.nlm.nih.gov/articles/PMC3003214/">https://pmc.ncbi.nlm.nih.gov/articles/PMC3003214/</a></p>
<p id="ref-5"><a href="https://link.springer.com/article/10.1186/s12906-024-04477-3" class="ref-marker">[5]</a> Effects of grape seed extract supplementation on cardiovascular risk factors, liver enzymes: <a href="https://link.springer.com/article/10.1186/s12906-024-04477-3">https://link.springer.com/article/10.1186/s12906-024-04477-3/</a></p>
<p id="ref-6"><a href="https://pmc.ncbi.nlm.nih.gov/articles/PMC5549431/" class="ref-marker">[6]</a> Effect of injectable glutathione for treatment of liver disease: <a href="https://pmc.ncbi.nlm.nih.gov/articles/PMC5549431/">https://pmc.ncbi.nlm.nih.gov/articles/PMC5549431/</a></p>
<p id="ref-7"><a href="https://pmc.ncbi.nlm.nih.gov/articles/PMC8234027/" class="ref-marker">[7]</a> How the body synthesises NAC into glutathione: <a href="https://pmc.ncbi.nlm.nih.gov/articles/PMC8234027/">https://pmc.ncbi.nlm.nih.gov/articles/PMC8234027/</a></p>
<p id="ref-8"><a href="https://pmc.ncbi.nlm.nih.gov/articles/PMC3844502/" class="ref-marker">[8]</a> Baseline clinical study about TMG which shows it is promising for use in lifting: <a href="https://pmc.ncbi.nlm.nih.gov/articles/PMC3844502/">https://pmc.ncbi.nlm.nih.gov/articles/PMC3844502/</a></p>

<style>
  .img-lightbox-trigger { cursor: zoom-in; }
  #img-lightbox {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 10000;
    align-items: center;
    justify-content: center;
    padding: 40px;
    box-sizing: border-box;
    background: rgba(0, 0, 0, 0);
    backdrop-filter: blur(0px);
    transition: background 0.35s ease, backdrop-filter 0.35s ease;
    cursor: zoom-out;
  }
  #img-lightbox.is-open {
    background: rgba(0, 0, 0, 0.85);
    backdrop-filter: blur(6px);
  }
  #img-lightbox img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    border-radius: 8px;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
    transform: scale(0.85);
    opacity: 0;
    transition: transform 0.35s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.3s ease;
  }
  #img-lightbox.is-open img {
    transform: scale(1);
    opacity: 1;
  }
  .img-lightbox-close {
    position: absolute;
    top: 18px;
    right: 24px;
    font-size: 2em;
    line-height: 1;
    color: rgba(255, 255, 255, 0.8);
    background: none;
    border: none;
    cursor: pointer;
    font-family: sans-serif;
    user-select: none;
  }
  .img-lightbox-hint {
    position: absolute;
    bottom: 18px;
    left: 50%;
    transform: translateX(-50%);
    color: rgba(255, 255, 255, 0.55);
    font-family: sans-serif;
    font-size: 0.82em;
    letter-spacing: 1.5px;
    user-select: none;
    pointer-events: none;
  }
</style>

<div id="img-lightbox">
  <button class="img-lightbox-close" aria-label="Close">&#x2715;</button>
  <img src="" alt="" />
  <span class="img-lightbox-hint">click anywhere to dismiss</span>
</div>

<script>
  (function () {
    var lightbox = document.getElementById('img-lightbox');
    if (!lightbox) return;
    var lightboxImg = lightbox.querySelector('img');
    var main = document.querySelector('main') || document.body;

    function openLightbox(src, alt) {
      lightboxImg.src = src;
      lightboxImg.alt = alt || '';
      lightbox.style.display = 'flex';
      document.body.style.overflow = 'hidden';
      requestAnimationFrame(function () {
        requestAnimationFrame(function () {
          lightbox.classList.add('is-open');
        });
      });
    }

    function closeLightbox() {
      lightbox.classList.remove('is-open');
      setTimeout(function () {
        lightbox.style.display = 'none';
        lightboxImg.src = '';
        document.body.style.overflow = '';
      }, 350);
    }

    Array.prototype.forEach.call(main.querySelectorAll('img'), function (img) {
      if (img.closest('#img-lightbox')) return;
      img.classList.add('img-lightbox-trigger');
      img.addEventListener('click', function (e) {
        var anchor = img.closest('a');
        if (anchor) e.preventDefault();
        e.stopPropagation();
        openLightbox(img.currentSrc || img.src, img.alt);
      });
    });

    lightbox.addEventListener('click', closeLightbox);
    document.addEventListener('keydown', function (e) {
      if (e.key === 'Escape' && lightbox.classList.contains('is-open')) closeLightbox();
    });
  })();
</script>]]></content><author><name>Sean Sullivan</name></author><category term="personal" /><category term="health" /><summary type="html"><![CDATA[Earlier in 2025, I did bloodwork for the first time in a while, and found I had some insanely high liver enzymes. I’d come off the heels of five years of college, having spent the last ~year and a half drinking like my liver was bulletproof. I realized that something needed to change, and spent the next year of my life committed to achieving the healthiest liver possible. Turns out, if you take care of your liver, it most definitely will take care of you too.]]></summary></entry><entry><title type="html">[TOOL] A better way to track blood test results</title><link href="https://sull1van.com/tracking-blood-tests.html" rel="alternate" type="text/html" title="[TOOL] A better way to track blood test results" /><published>2026-05-18T00:00:00+00:00</published><updated>2026-05-18T00:00:00+00:00</updated><id>https://sull1van.com/tracking-blood-tests</id><content type="html" xml:base="https://sull1van.com/tracking-blood-tests.html"><![CDATA[<style>
  .liver-enzymes-tooltip {
    border-bottom: 3px solid var(--tooltip-accent);
    cursor: pointer;
    position: relative;
    display: inline;
    outline-offset: 0.2em;
  }
  .liver-enzymes-tooltip:focus-visible {
    outline: 2px solid var(--tooltip-accent);
    border-radius: 0.15em;
  }
  /* Default: render on top of the text when screenspace is limited or JS is unavailable */
  .tooltip-card-container {
    position: absolute;
    bottom: 130%;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s cubic-bezier(0.4, 0, 0.2, 1);
    z-index: 100;
  }
  .liver-enzymes-tooltip:not(.is-hover-suppressed):hover .tooltip-card-container,
  .liver-enzymes-tooltip:focus-visible .tooltip-card-container,
  .liver-enzymes-tooltip.is-pinned .tooltip-card-container {
    opacity: 1;
    pointer-events: auto;
  }
  .tooltip-connector-line {
    display: none;
  }

  .tooltip-card-container.is-measured {
    position: fixed;
    bottom: auto;
    left: var(--tooltip-left);
    top: var(--tooltip-top);
  }
  .tooltip-card-container.is-margin {
    transform: translateY(-50%);
    flex-direction: row;
    align-items: center;
  }
  .tooltip-card-container.is-margin.is-left {
    flex-direction: row-reverse;
  }
  .liver-enzymes-tooltip:not(.is-hover-suppressed):hover .tooltip-card-container.is-margin,
  .liver-enzymes-tooltip:focus-visible .tooltip-card-container.is-margin,
  .liver-enzymes-tooltip.is-pinned .tooltip-card-container.is-margin {
    transform: translateY(-50%);
  }
  .tooltip-card-container.is-margin .tooltip-connector-line {
    display: block;
    width: var(--tooltip-connector-width, 40px);
    height: 3px;
    background: var(--tooltip-accent);
    flex-shrink: 0;
  }
  .tooltip-card-container.is-margin .tooltip-card {
    position: relative;
  }

  .tooltip-card {
    width: 153px;
    background: var(--tooltip-card-bg);
    border: 1px solid var(--tooltip-card-border);
    border-radius: 0;
    padding: 0.935rem 1.02rem;
    box-shadow: var(--tooltip-card-shadow);
    font-family: inherit;
    color: inherit;
    display: flex;
    flex-direction: column;
    flex-shrink: 0;
  }
  .biomarker-item {
    text-align: center;
    display: block;
  }
  .biomarker-item:first-child {
    margin-bottom: 0.85rem;
    padding-bottom: 0.85rem;
    border-bottom: 1px solid var(--tooltip-divider);
  }
  .biomarker-value {
    font-size: 1.77rem;
    font-weight: 800;
    color: var(--tooltip-value);
    line-height: 1;
    letter-spacing: 0;
    display: block;
  }
  .biomarker-name {
    font-size: 0.85rem;
    font-weight: 700;
    letter-spacing: 0;
    margin-top: 0.25rem;
    display: block;
  }
  .biomarker-range {
    font-size: 0.8625rem;
    margin-top: 0.1rem;
    opacity: 0.7;
    display: block;
  }
  .biomarker-source {
    align-self: flex-end;
    font-size: 0.68rem;
    font-style: italic;
    line-height: 1.2;
    margin-top: 0.8rem;
    opacity: 0.65;
    text-align: right;
  }
  /* Note cards styled globally in the post layout */
</style>

<script>
  document.addEventListener('DOMContentLoaded', function () {
    var triggers = Array.prototype.slice.call(document.querySelectorAll('.liver-enzymes-tooltip'));
    var marginGap = 18;
    var viewportPadding = 16;

    function positionTooltip(trigger) {
      var cardContainer = trigger.querySelector('.tooltip-card-container');
      var card = trigger.querySelector('.tooltip-card');
      var connector = trigger.querySelector('.tooltip-connector-line');
      var main = trigger.closest('main') || document.querySelector('main');

      if (!cardContainer || !card || !main) return;

      cardContainer.classList.remove('is-measured', 'is-margin', 'is-left');
      cardContainer.style.removeProperty('--tooltip-left');
      cardContainer.style.removeProperty('--tooltip-top');
      cardContainer.style.removeProperty('--tooltip-connector-width');

      var mainRect = main.getBoundingClientRect();
      var triggerRect = trigger.getBoundingClientRect();
      var cardRect = card.getBoundingClientRect();
      var connectorWidth = connector ? connector.getBoundingClientRect().width : 40;
      var neededWidth = cardRect.width + connectorWidth + marginGap;
      var rightSpace = window.innerWidth - mainRect.right - marginGap - viewportPadding;
      var leftSpace = mainRect.left - marginGap - viewportPadding;
      var cardTop = Math.min(
        window.innerHeight - viewportPadding - cardRect.height / 2,
        Math.max(viewportPadding + cardRect.height / 2, triggerRect.top + triggerRect.height / 2)
      );

      if (rightSpace >= neededWidth) {
        var connectorWidthPx = Math.min(56, Math.max(24, rightSpace - cardRect.width));
        cardContainer.classList.add('is-measured', 'is-margin');
        cardContainer.style.setProperty('--tooltip-left', (mainRect.right + marginGap) + 'px');
        cardContainer.style.setProperty('--tooltip-top', cardTop + 'px');
        cardContainer.style.setProperty('--tooltip-connector-width', connectorWidthPx + 'px');
        return;
      }

      if (leftSpace >= neededWidth) {
        var leftConnector = Math.min(56, Math.max(24, leftSpace - cardRect.width));
        cardContainer.classList.add('is-measured', 'is-margin', 'is-left');
        cardContainer.style.setProperty('--tooltip-left', (mainRect.left - leftConnector - cardRect.width) + 'px');
        cardContainer.style.setProperty('--tooltip-top', cardTop + 'px');
        cardContainer.style.setProperty('--tooltip-connector-width', leftConnector + 'px');
        return;
      }

      var centeredLeft = Math.min(
        window.innerWidth - viewportPadding - cardRect.width / 2,
        Math.max(viewportPadding + cardRect.width / 2, triggerRect.left + triggerRect.width / 2)
      );
      var aboveTop = triggerRect.top - marginGap - cardRect.height;
      var belowTop = triggerRect.bottom + marginGap;
      var stackedTop = aboveTop >= viewportPadding ? aboveTop : belowTop;

      cardContainer.classList.add('is-measured');
      cardContainer.style.setProperty('--tooltip-left', centeredLeft + 'px');
      cardContainer.style.setProperty('--tooltip-top', Math.min(
        window.innerHeight - viewportPadding - cardRect.height,
        Math.max(viewportPadding, stackedTop)
      ) + 'px');
    }

    function refreshOpenTooltips() {
      triggers.forEach(function (trigger) {
        if ((trigger.matches(':hover') && !trigger.classList.contains('is-hover-suppressed')) || trigger.matches(':focus-visible') || trigger.classList.contains('is-pinned')) {
          positionTooltip(trigger);
        }
      });
    }

    triggers.forEach(function (trigger) {
      var cardContainer = trigger.querySelector('.tooltip-card-container');

      if (cardContainer) {
        cardContainer.addEventListener('click', function (event) {
          event.stopPropagation();
        });
      }

      trigger.addEventListener('mouseenter', function () {
        positionTooltip(trigger);
      });
      trigger.addEventListener('mouseleave', function () {
        trigger.classList.remove('is-hover-suppressed');
      });
      trigger.addEventListener('focus', function () {
        positionTooltip(trigger);
      });
      trigger.addEventListener('click', function (event) {
        event.stopPropagation();
        var wasPinned = trigger.classList.contains('is-pinned');

        if (wasPinned) {
          trigger.classList.remove('is-pinned');
          trigger.classList.add('is-hover-suppressed');
          trigger.setAttribute('aria-expanded', 'false');
          return;
        }

        trigger.classList.remove('is-hover-suppressed');
        trigger.classList.add('is-pinned');
        trigger.setAttribute('aria-expanded', 'true');
        positionTooltip(trigger);
      });
      trigger.addEventListener('keydown', function (event) {
        if (event.key === 'Enter' || event.key === ' ') {
          event.preventDefault();
          trigger.click();
        }
        if (event.key === 'Escape') {
          trigger.classList.remove('is-pinned');
          trigger.setAttribute('aria-expanded', 'false');
        }
      });
    });

    document.addEventListener('click', function () {
      triggers.forEach(function (trigger) {
        trigger.classList.remove('is-pinned');
        trigger.setAttribute('aria-expanded', 'false');
      });
    });
    window.addEventListener('resize', refreshOpenTooltips);
  });
</script>

<p>Over one year ago, I made the decision to start focusing on my bloodwork. I had just gotten the first comprehensive metabolic panel in years, and the results weren’t great. <span class="liver-enzymes-tooltip" role="button" tabindex="0" aria-expanded="false">My liver enzymes ALT and AST<span class="tooltip-card-container"><span class="tooltip-connector-line"></span><span class="tooltip-card"><span class="biomarker-item"><span class="biomarker-value">147</span><span class="biomarker-name">AST</span><span class="biomarker-range">Normal: 10–40 U/L</span></span><span class="biomarker-item"><span class="biomarker-value">71</span><span class="biomarker-name">ALT</span><span class="biomarker-range">Normal: 9–46 U/L</span></span><span class="biomarker-source">Source: LabCorp, March 2025</span></span></span></span> were extremely high, in such an embarrassing way that it basically screamed <em>this person drinks too much alcohol</em> [1]. I realized that a bigger effort was needed if I was going to take charge of my health.</p>

<div class="post-toc post-toc--soft">
  <div class="post-toc-title">Table of Contents</div>
  <ul>
    <li><a href="#my-plan">My Plan</a></li>
    <li><a href="#how-it-went">How it went</a></li>
    <li class="nested"><a href="#steps-1-4-data-conversion">Steps 1-4: Data conversion</a></li>
    <li class="nested"><a href="#step-5-the-dashboard">Step 5: The Dashboard</a></li>
    <li class="nested"><a href="#the-frontend">The Frontend</a></li>
    <li class="nested"><a href="#the-backend">The Backend</a></li>
    <li><a href="#closing-thoughts">Closing thoughts</a></li>
    <li class="nested"><a href="#references">References</a></li>
  </ul>
</div>

<p>I started by looking at the data. Luckily for me, I’ve always had some sort of a focus on health, and I already had some two-dozen PDFs of blood test results dating back to 2018 in a folder on my computer. Every time I would get one, I’d save the results from the doctor as a PDF and drop it into that folder. While it was great to have, it was a mess to actually go through. I really wanted to make some comprehensive Excel spreadsheet with all of it, but assumed it would be too much work for one person to do.</p>

<div style="text-align: center; margin: 2rem auto;">
    <img src="/assets/images/2026-05-18-tracking-blood-tests/bloodTest.png" alt="List of PDFs" style="max-width: 100%; height: auto;" />
</div>

<h2 id="my-plan">My Plan</h2>

<p>My plan was pretty simple, just:</p>
<ol>
  <li>Command Claude or Codex to delegate an army of subagents to process all my PDFs</li>
  <li>File by file, comprehensively pull all numeric and non-numeric test results out</li>
  <li>Create a master datasheet with all these results</li>
  <li>Run a separate set of agents to check the first agents’ work, and report any inaccuracies they find.</li>
  <li>Create a central dashboard to read and manage all my blood test results</li>
</ol>

<p>It’s a lot. But since AI resources are virtually infinite, I was confident that it could be built.</p>

<h2 id="how-it-went">How it went</h2>

<h3 id="steps-1-4-data-conversion">Steps 1-4: Data conversion</h3>
<p>This was honestly easier than I expected. Claude and Codex both did a great job dispatching agents and converting the blood test results into an Excel sheet. The cool part is the verification bots didn’t find any actual errors, they just flagged places where the wrong units were used, like an ALT test from 2018 in ng/dL while the 2020 ALT was in ug/L. I did a manual spot check across the whole dataset and it looked great.</p>

<div style="text-align: center; margin: 2rem auto;">
    <img src="/assets/images/2026-05-18-tracking-blood-tests/bloodTestExcel.png" alt="List of PDFs" style="max-width: 100%; height: auto;" />
</div>

<h3 id="step-5-the-dashboard">Step 5: The Dashboard</h3>

<p>With the data in <em>some</em> kind of usable format, this was the part where I had some fun. I started by asking Claude and Codex to both design a rudimentary visual for the labs. My idea was pretty simple. It would have a dual layout, card-based and list-based, where you pick between the two views and get either one card or one list item per blood test. They always show the most recent result and its unit, and they’re color coded green or red depending on whether the result falls outside the normal range.</p>

<details class="note-card">
  <summary>Note</summary>
  <div class="note-card-body">
    <p>But what counts as a ‘normal range’? Depends who you ask! My results often showed different reference ranges for the same test across the years, which I mostly chalk up to the slight differences in how LabCorp and Quest Diagnostics calculate their normal ranges. Within a single company I didn’t see much variation.</p>
    <p>Either way, I built a system to handle it. Each blood test record, both in my backend database and in my spreadsheet, includes the reference range the lab gave me at the time of the test. The web UI parses this and shows the most recent range. These tests don't always come with a range, so the site keeps crawling older and older records until it finds one, and that’s the reference  you see on the display.</p>
  </div>
</details>

<h3 id="the-frontend">The Frontend</h3>

<p>Claude iterated on my design a few times, and the early prototypes were ugly. Inspired by the latest iOS update and wanting something a bit better than flat, I pushed the AI toward a glassmorphic UI. I’m really proud of how it turned out.</p>

<div class="post-gallery">
  <!-- Row 1: screen1 & screen2 + caption -->
  <div class="post-gallery-row post-gallery-row--2-1">
    <div class="post-gallery-images">
      <img src="/assets/images/2026-05-18-tracking-blood-tests/screen1.jpg" alt="Prototype Card View" class="post-gallery-img" />
      <img src="/assets/images/2026-05-18-tracking-blood-tests/screen2.jpg" alt="Prototype List View" class="post-gallery-img" />
    </div>
    <div class="post-gallery-caption">
      Card versus list UI view
    </div>
  </div>

  <!-- Row 2: screen3 + caption -->
  <div class="post-gallery-row post-gallery-row--1-1">
    <div>
      <img src="/assets/images/2026-05-18-tracking-blood-tests/screen3.jpg" alt="Midnight Mode" class="post-gallery-img" />
    </div>
    <div class="post-gallery-caption">
      The UI comes with many different modes, meant to highlight different points throughout the day. I wanted to simulate the UI of the Apple Weather app, because that is my ideal design for something that shows health data. It actually took a long time to achieve this UI, so I'm proud of the result.
    </div>
  </div>

  <!-- Row 3: screen4 & screen5 + caption -->
  <div class="post-gallery-row post-gallery-row--2-1">
    <div class="post-gallery-images">
      <img src="/assets/images/2026-05-18-tracking-blood-tests/screen4.jpg" alt="Detail View" class="post-gallery-img" />
      <img src="/assets/images/2026-05-18-tracking-blood-tests/screen5.jpg" alt="History and Context Menus" class="post-gallery-img" />
    </div>
    <div class="post-gallery-caption">
      **Left**: detail view showing most recent test, normal range, and units. **Right**: view when you scroll down. Shows all test history, and offers context menus which present additional options
    </div>
  </div>

  <!-- Row 4: screen6 -->
  <div class="post-gallery-row">
    <div style="max-width: 100%; margin: 0 auto; width: 100%;">
      <img src="/assets/images/2026-05-18-tracking-blood-tests/screen6.jpg" alt="Prototype Screen 6" class="post-gallery-img" />
    </div>
        <div class="post-gallery-caption">
      The card view with daytime mode enabled. It was extremely hard to get the UI to this state, so honestly I'm blown away it all works.
    </div>
  </div>

  <!-- Row 5: screen7 + caption -->
  <div class="post-gallery-row post-gallery-row--1-1">
    <div>
      <img src="/assets/images/2026-05-18-tracking-blood-tests/screen7.jpg" alt="Prototype Screen 7" class="post-gallery-img" />
    </div>
    <div class="post-gallery-caption">
      Screenshot of Cmd+K. I don't have a better name for it, but it's triggered by Cmd+K on desktop, so 
    </div>
  </div>
</div>

<p>Once I finished, I spun up some more Claude subagents to do bug catching, and in the middle of that one of them suggested a new feature I really liked. That’s what you’re seeing in the last screenshot, actually. It’s a power menu that’s triggered by tapping the little flask on mobile or hitting Cmd+K on desktop. When you open it, you can instantly pull up test results, create an export PDF, or even add a new lab. It’s really powerful and designed to be my place to drop in when I need to locate a result as fast as possible.</p>

<hr />

<p>That’s pretty much the entirety of the UI. I really loved designing it, especially the glass background. I was going for an imitation of Apple Weather, and I think we (me/Claude) nailed it.</p>

<h3 id="the-backend">The Backend</h3>

<p>For backend storage I went with Google Firebase. The only real alternative people seem to be using nowadays is Supabase, and that has an awful free tier. Google’s looked better for the long haul. But since Google prices based on # reads, the data model I ended up with is honestly pretty funny.</p>

<p>Firebase gives you 50K reads/writes a day for free. After that it’s some absurdly low rate, like $0.03 / 100K reads (i think). The other great thing is the 1MB data record limit. 1 megabyte! 😂 That’s about 1 million characters. For reference, the Great Gatsby comes in around 240,000. My blood test results are never going to be as long as the Great Gatsby, so therefore I decided to store <strong>my entire database in one Firebase entry</strong>.</p>

<p>It’s safe to say that this setup will never cost me a dime. The only remaining question is what the data will look like when we send it to Firebase. I iterated with Claude, and we settled on the following schema for a master format:</p>
<pre><code class="language-json">  {
    "schemaVersion": 1,
    "tests": [
      {
        "name": "string",
        "unit": "",
        "range": "",
        "type": "",
        "points": [
          {
            "date": "YYYY-MM-DD",
            "rawResult": "",
            "lab": "",
            "sourceFile": "",
            "testResultId": "",
            "rawRange": "",
            "unit": "",
            "sourcePage": "",
            "reviewStatus": "",
            "verificationStatus": ""
          }
        ]
      }
    ]
  }
</code></pre>

<p>This schema looked pretty good. I sent it to firebase, but then realized I just stored private health data in plaintext, which is stupid. It definitely needed to be obfuscated. I thought about just encrypting the values themselves, and leaving the json keys themselves plaintext. But that is also pointless since the metadata (test name, test date) matters just as much. So I settled on a Base64 AES-GCM ciphertext of JSON.stringify(vaultData), which turns the whole thing into a string and encrypts all of it.</p>

<hr />

<p>With that, it finally looked good. I wired up the Firebase integration and ran a one-time script to push all my data, and it worked on the first try. I’ve been using this site ever since then to track my test results.</p>

<p>The firestore database has essentially become my new source of truth. I still make regular exports so there’s the Firestore database and a Excel sheet running in parallel, giving me dual sources of truth. It’s a little extra effort, but I want to be protected in case something gets mangled in the database and my data becomes unusable.</p>

<h2 id="closing-thoughts">Closing thoughts</h2>

<p>This project was genuinely a lot of fun. I reach for the web app whenever I need to look up a blood test value, and whenever I bump into a new bug or feature idea I can just build it. Over time I’ve added a ton of functionality, and it’s become a really solid home for my data. It’s also easy to share it, making conversations with doctors and family much easier. I might publish this web app to Github if there is interest, but for right now it’s just a happy webapp that sits on my phone.</p>

<p><em>It also helps feed my obsession of actually trying to optimize these numbers. Since creating this dashboard, I actually did a whole project where I used it to help dial in my supplement routine and help out my liver. If you’re interested, feel free to take a look at that <a href="https://sull1van.com/best-liver-of-all-time">here</a>.</em></p>

<h3 id="references">References</h3>
<p>[1] Per NIH, <a href="https://pmc.ncbi.nlm.nih.gov/articles/PMC4155359/">https://pmc.ncbi.nlm.nih.gov/articles/PMC4155359/</a>: 
  “In most types of liver damage, ALT is higher than AST. However, in alcohol-related liver injury, the enzyme AST is typically two to three times higher than ALT. An AST-to-ALT ratio greater than 2:1 strongly suggests alcohol is the cause.”</p>

<style>
  .img-lightbox-trigger { cursor: zoom-in; }
  #img-lightbox {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 10000;
    align-items: center;
    justify-content: center;
    padding: 40px;
    box-sizing: border-box;
    background: rgba(0, 0, 0, 0);
    backdrop-filter: blur(0px);
    transition: background 0.35s ease, backdrop-filter 0.35s ease;
    cursor: zoom-out;
  }
  #img-lightbox.is-open {
    background: rgba(0, 0, 0, 0.85);
    backdrop-filter: blur(6px);
  }
  #img-lightbox img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    border-radius: 8px;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
    transform: scale(0.85);
    opacity: 0;
    transition: transform 0.35s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.3s ease;
  }
  #img-lightbox.is-open img {
    transform: scale(1);
    opacity: 1;
  }
  .img-lightbox-close {
    position: absolute;
    top: 18px;
    right: 24px;
    font-size: 2em;
    line-height: 1;
    color: rgba(255, 255, 255, 0.8);
    background: none;
    border: none;
    cursor: pointer;
    font-family: sans-serif;
    user-select: none;
  }
  .img-lightbox-hint {
    position: absolute;
    bottom: 18px;
    left: 50%;
    transform: translateX(-50%);
    color: rgba(255, 255, 255, 0.55);
    font-family: sans-serif;
    font-size: 0.82em;
    letter-spacing: 1.5px;
    user-select: none;
    pointer-events: none;
  }
</style>

<div id="img-lightbox">
  <button class="img-lightbox-close" aria-label="Close">&#x2715;</button>
  <img src="" alt="" />
  <span class="img-lightbox-hint">click anywhere to dismiss</span>
</div>

<script>
  (function () {
    var lightbox = document.getElementById('img-lightbox');
    if (!lightbox) return;
    var lightboxImg = lightbox.querySelector('img');
    var main = document.querySelector('main') || document.body;

    function openLightbox(src, alt) {
      lightboxImg.src = src;
      lightboxImg.alt = alt || '';
      lightbox.style.display = 'flex';
      document.body.style.overflow = 'hidden';
      requestAnimationFrame(function () {
        requestAnimationFrame(function () {
          lightbox.classList.add('is-open');
        });
      });
    }

    function closeLightbox() {
      lightbox.classList.remove('is-open');
      setTimeout(function () {
        lightbox.style.display = 'none';
        lightboxImg.src = '';
        document.body.style.overflow = '';
      }, 350);
    }

    Array.prototype.forEach.call(main.querySelectorAll('img'), function (img) {
      if (img.closest('#img-lightbox')) return;
      img.classList.add('img-lightbox-trigger');
      img.addEventListener('click', function (e) {
        var anchor = img.closest('a');
        if (anchor) e.preventDefault();
        e.stopPropagation();
        openLightbox(img.currentSrc || img.src, img.alt);
      });
    });

    lightbox.addEventListener('click', closeLightbox);
    document.addEventListener('keydown', function (e) {
      if (e.key === 'Escape' && lightbox.classList.contains('is-open')) closeLightbox();
    });

    // Note-card toggling handled globally in the post layout.
  })();
</script>]]></content><author><name>Sean Sullivan</name></author><category term="personal" /><category term="tech" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">[PROJECT] 7,500 Miles in a Self-Driving Car</title><link href="https://sull1van.com/7500-miles-self-driving-car.html" rel="alternate" type="text/html" title="[PROJECT] 7,500 Miles in a Self-Driving Car" /><published>2026-05-15T00:00:00+00:00</published><updated>2026-05-15T00:00:00+00:00</updated><id>https://sull1van.com/7500-miles-self-driving-car</id><content type="html" xml:base="https://sull1van.com/7500-miles-self-driving-car.html"><![CDATA[<div id="splash-background"></div>
<div id="kia2-background"></div>
<div id="kia3-background"></div>
<div id="kia4-background"></div>

<style>

  #splash-background {
    position: absolute;
    bottom: 0;
    left: 50%;
    transform: translateX(-50%);
    width: 100vw;
    height: 100vh;
    background-image: url('/assets/images/2026-05-15-7500-miles-self-driving-car/splash.jpeg');
    background-size: auto 122%;
    background-position: center top;
    background-repeat: no-repeat;
    z-index: -3;
    -webkit-mask-image: linear-gradient(to top, black 0%, transparent 70%);
    mask-image: linear-gradient(to top, black 0%, transparent 70%);
  }

  #kia2-background {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 115vh;
    height: 100vw;
    transform: translate(-50%, -50%) rotate(90deg);
    background-image: url('/assets/images/2026-05-15-7500-miles-self-driving-car/kia2.jpg');
    background-size: cover;
    background-position: center center;
    z-index: -3;
    opacity: 0.5;
    -webkit-mask-image: linear-gradient(to top, black 0%, rgba(0,0,0,0.1) 60%, rgba(0,0,0,0.1) 100%), linear-gradient(to right, transparent 0%, black 15%, black 85%, transparent 100%);
    -webkit-mask-composite: source-in;
    mask-image: linear-gradient(to top, black 0%, rgba(0,0,0,0.1) 60%, rgba(0,0,0,0.1) 100%), linear-gradient(to right, transparent 0%, black 15%, black 85%, transparent 100%);
    mask-composite: intersect;
  }

  #kia3-background {
    position: absolute;
    top: 0;
    left: 50%;
    transform: translateX(-50%);
    width: 100vw;
    height: 100vh;
    background-image: url('/assets/images/2026-05-15-7500-miles-self-driving-car/kia3.JPG');
    background-size: cover;
    background-position: center top;
    z-index: -3;
    -webkit-mask-image: linear-gradient(to bottom, black 0%, black 60vh, transparent 80vh);
    mask-image: linear-gradient(to bottom, black 0%, black 60vh, transparent 80vh);
  }

  #kia4-background {
    position: absolute;
    top: 75%;
    left: 50%;
    width: 115vh;
    height: 100vw;
    transform: translate(-50%, -50%) rotate(-90deg);
    background-image: url('/assets/images/2026-05-15-7500-miles-self-driving-car/kia5.jpeg');
    background-size: cover;
    background-position: center center;
    z-index: -3;
    opacity: 0.5;
    -webkit-mask-image: linear-gradient(to top, black 0%, rgba(0,0,0,0.1) 60%, rgba(0,0,0,0.1) 100%), linear-gradient(to right, transparent 0%, black 15%, black 85%, transparent 100%);
    -webkit-mask-composite: source-in;
    mask-image: linear-gradient(to top, black 0%, rgba(0,0,0,0.1) 60%, rgba(0,0,0,0.1) 100%), linear-gradient(to right, transparent 0%, black 15%, black 85%, transparent 100%);
    mask-composite: intersect;
  }


  /* Keep the page canvas themed without washing over the background images. */
  html,
  html[data-theme="light"] {
    background: #fff;
  }
  body {
    position: relative;
    padding-bottom: 70vh;
    background: transparent !important;
  }
  footer {
    position: absolute;
    left: 0;
    right: 0;
    bottom: max(12vh, 5rem);
    z-index: 1;
    background: transparent;
    color: #eee;
    text-shadow: 0 1px 8px rgba(0, 0, 0, 0.9), 0 1px 2px rgba(0, 0, 0, 0.95);
  }
  footer hr {
    display: none;
  }
  footer a:link,
  footer a:visited,
  footer a:focus,
  footer a:hover,
  footer a:active {
    color: #eef;
  }
  html[data-theme="dark"] {
    background: var(--bg);
  }
  @media (prefers-color-scheme: dark) {
    html {
      background: var(--bg);
    }
    html[data-theme="light"] {
      background: #fff;
    }
  }

  /* Title styling */
  h1 {
    margin-top: 0;
    padding-top: 70vh;
    font-size: 2.3em;
  }
</style>

<h2 id="one-month-on-the-road-with-a-self-driving-car">One month on the road with a self-driving car</h2>

<p>In summer 2025, I had a pretty big goal. I wanted to drive across the entire western half of the country on a solo road trip, within the span of one month.</p>

<p>It took weeks to plan out the complete itinerary, which involved stops in over 23 states, and visiting with twelve different friends all across the country, plus working out of three different company headquarters locations.</p>

<p>But the coolest part of the trip (by FAR) was how I did it with the help of a Comma 3X.</p>

<p>I set it up in the 2-3 weeks before the trip, and got all the kinks worked out just in time. In the end, the Comma handled the vast majority of highway driving, and I only ended up doing that last 30-40% of each drive manually.</p>

<p>I’d love to show you how I did it!</p>

<h3 id="what-is-a-comma-3x">What is a Comma 3X</h3>

<p>So Comma.ai is the name of the company, and the 3X is a small, windshield-mounted computer. It takes control of the steering in <em>most</em> production cars. It runs their custom software called OpenPilot, which is a fully customizable user interface for the device.</p>

<p>At first, I saw that <a href="https://comma.ai/vehicles">my Kia wasn’t supported</a>, so I gave up my hopes of autonomous driving as soon as I got this car in 2024. A year later,though, I joined a Discord and found out that several other Kia owners had retrofitted this to their (newer) cars, so I could do it too. I just had to use this obscure fork of the software I found.</p>

<p>Some helpful background: Comma’s software is open source, which means the official version is only <em>stock</em> openpilot. There are plenty of community forks for different cars, different preferences, and edge cases that Comma decided not to support. To that end, a group known as Sunnypilot actually made their own fork of it, adding new features. And within that Sunnypilot Github repo, there’s this fork some Hyundai/Kia/Genesis (HKG) owners made. THAT’S the one that I use. So if you end up googling Comma openpilot and see your car isn’t supported, I highly recommend doing some more research. In my case, my car <strong>wasn’t</strong> supported, but all I had to do was join the Discord, learn what kind of harness I’d need, buy that one, and figure out who in the community had already forked the code.</p>

<p><img src="https://blog.comma.ai/img/comma3X/cover.png" alt="Comma 3X" style="max-width: 70%; height: auto;" /></p>

<h2 id="installing-it">Installing it</h2>

<p>This is where it gets fun..</p>

<p>You’ll need to look up the Comma setup video specific to your car. I found that all HKG cars have similar installation instructions, so it was pretty easy to get mine put in. 5 minutes of looking through YouTube and you should be on your way.</p>

<p><img src="/assets/images/2026-05-15-7500-miles-self-driving-car/commaInstallation_hyundai.png" alt="Comma 3X installation" style="max-width: 100%; height: auto;" /></p>

<p>The interesting thing about the Comma 3X is that it sits between your car and the camera. It intercepts the feed coming straight from the camera, decodes it, and uses it for autonomous control. It also has a genius passthrough mechanism where it will pass the camera footage straight through to the car if the Comma loses power. When driving, this would save me in the rare instances in which the Comma was annoying me and I pulled its power plug. Once you do that, the car defaults to its own controls without any issue. It’s a highly resilient setup.</p>

<h2 id="setting-it-up">Setting it up</h2>

<h3 id="first-launch">First launch</h3>
<p>By far the hardest thing to work on with a Comma is the software. It will install openpilot by default, which will fuck you over if you are like me and don’t have a supported car. Don’t do this! You will spend <em>so much time</em> trying to force a factory reset only to reinstall openpilot by accident.</p>

<p>On setup, you need to choose “Custom software”, and enter in a link. What link exactly? This is where it gets weird.</p>

<p>After a ton of research, I learned you can point the Comma at a website with a release image of the software you want. It’s nearly impossible to figure it out, though. I literally could not find the link for sunnypilot. But then I learned that Comma will actually do it for you, as they host Sunnypilot on their own domain. You just type in “sunnypilot” in the custom software URL box, and that’s it. For me, I’m using a <strong>branch</strong> of the sunnypilot GitHub repo, so I do “sunnypilot/ccnc-port”.</p>

<h3 id="getting-the-specifics-right">Getting the specifics right</h3>

<p>There are a million variables to configure once your Comma fully boots. The Comma will try to identify your car’s fingerprint. 
  Fingerprinting is essentially the Comma identifying what car you own, and what APIs it’s going to need to interact with to control your steering. By default, it <em>should</em> be able to fingerprint your car. If it can’t, you’re screwed. It will let you choose a car manually from the list, but the fact that it couldn’t figure it out automatically means it can’t communicate with your car properly, so you really can’t choose it manually. This happened to me <em>a lot</em> when I would try different branches of Sunnypilot, and led to me doing endless factory resets. For me, the only branch of Sunnypilot that can fingerprint my car is ccnc-port, so make sure you use the appropriate port for your car. You can search the Sunnypilot Discord for your make and model and see what others did to get it set up.</p>

<p>After fingerprinting, you should go into the settings menu and start configuring things to your liking. Using custom settings, you can have it display the current speed limit, your current speed, and many other cool metrics. I turn most of these on. One thing Comma does that I’ve never seen anywhere else is it will actually show you the speed of the car in front of you. I don’t know why car manufacturers don’t do this to begin with, since all modern ones are seeing this data with their ultrasound sensors. Either way, it’s great to have this on the Comma.</p>

<p>There are also a lot of configuration settings that will affect your driving. It comes with dozens of driving models, each one being about ~70MB a piece and containing a slightly modified version of a driving model based on who trained the data. Comma releases these regularly, as they have their own in-house datacenter that generates them. No model is ever the ‘best’ one, since all cars are different. You really just have to start driving and figure out which works well for you. For me, that meant choosing like ~10 models and just spending the entire day on the road testing them.</p>

<p>You’ll also want to look at additional things, like how you want lane changes and braking to work. The Comma won’t brake by default, and it won’t do lane changes by default, but it can if you want it to. I personally do automated lane change, but no braking, since the Comma is pretty shit at managing my speed.</p>

<h3 id="driver-monitoring">Driver monitoring</h3>

<p>By far the most ‘controversial’ aspect of the Comma is that it enables hands-free driving. To accomplish this without being reckless, Comma developed a driver monitoring system that runs at all time. The Comma 3X has a wide-angle camera which constantly watches the driver and runs a neural network to assess their attention. For example, if the driver uses a phone during driving, Comma will notice that and start beeping.</p>

<p>Since the software is completely open source, you might think you could change these settings. Turns out, <strong>you absolutely can</strong>. For anyone wondering, it’s two files, helpers.py and monitoring.py. I have done extensive amounts of testing with mine, and have arrived at a happy medium for monitoring: I do WANT the monitoring, since hands-free driving could lead to instances where I become inattentive to what’s on the road, but it shouldn’t be annoying. I wanted the system to notice real inattention without yelling at me every time I glanced at navigation or checked something quickly at a stop. So I ended up changing the code, but only slightly. You may want to do this too.</p>

<p>One thing I like about the attention tracking is that if Comma notices me being drowsy, it will make an extremely loud beep to wake me up. This <em>did happen</em> often when I would drive late at night, and I am very thankful for it. The monitoring you get with the Comma is honestly great peace of mind. You can also be assured that your face isn’t being recorded and uploaded anywhere, because you control the software, end to end. It’s great.</p>

<h3 id="beyond-the-basics-asking-for-help">Beyond the basics: Asking for help</h3>

<p>If you do try to get set up with this, there can be tons of issues. Driverless car technology is insanely complicated, and was extremely difficult to get set up even for someone like me. The great thing about buying a Comma 3X, though, is that you’re joining a huge community of car drivers just like you. Sunnypilot and Openpilot both have large Discord chats you can join, and a lot of the useful information is scattered across threads, branch names, harness recommendations, and people casually mentioning the one setting that makes everything work.</p>

<h2 id="taking-it-out-west">Taking it out West</h2>

<p>The Comma ended up coming with me on the trip, as I was able to get everything set up just in time. I would turn it on during highway driving and usually not much else. It’s not very well trained for steep turns, and will often overshoot them and drive the car slightly to the inside of the lane. Highway driving worked perfectly though, and it did a great job of keeping me centered. The really cool thing is that they’ve trained it in all kinds of driving scenarios, so it can reliably steer during the day, at night, and even during rain.</p>

<p>As I went across the country, I started using it more as a copilot than something which completely replaced my driving. For example, knowing I’ll be going through a stretch of straight, level highway with no one else meant that I’d turn it on and then focus more on the scenery than the drive. Sometimes I’d turn it on while I’m going to change climate settings or otherwise occupied, using it as insurance that I didn’t swerve when I did whatever the task was. I would also use it while I was actively steering, almost to provide insurance that I’d stay on the road. If I ever got too close to the edge of a lane, Comma would gently steer me back to the center (This is in contrast to cars that only steer to block lane departure, as they don’t continue steering to KEEP you in the middle of your lane. Comma does).</p>

<p>In all, it was a lot of fun. I really enjoyed being out West and I think the comma was part of the reason the trip went so well. It takes a lot of the headache out of driving, and makes it more of an adventure.</p>]]></content><author><name>Sean Sullivan</name></author><category term="personal" /><category term="tech" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">[TOOL]: Study for the FE with me</title><link href="https://sull1van.com/study-with-me.html" rel="alternate" type="text/html" title="[TOOL]: Study for the FE with me" /><published>2026-04-19T00:00:00+00:00</published><updated>2026-04-19T00:00:00+00:00</updated><id>https://sull1van.com/study-with-me</id><content type="html" xml:base="https://sull1van.com/study-with-me.html"><![CDATA[<h3 id="hello">Hello!</h3>

<p>Recently I’ve taken it upon myself to study for the FE exam. There’s a longer term career pivot in the works, but for now I’ve been focused on getting the best study material possible.</p>

<p>At first, I found the Kaplan/PPI study material. They have a <em>lot</em> of questions, but some of them were written poorly and also just incorrect. After paying $150 for a one month membership, I scraped all the questions I could find and ended up with a dataset of over 1000 questions. I don’t think they are as relevant to the exam, though, so I found another resource that I think is much better.</p>

<p>Enter <a href="https://sull1van.com/FEStudy">This site</a>. I found a reddit post from another engineer, who said he sourced as many FE questions as possible from around the web, and came up with this dataset. He posted it for free at https://journey2pe.com/. I took his question list and tried my best to parse out the questions vs. the answers, and then format it into a text-only database (which was tough, since it has images). I was able to use AI and spend about two weeks concocting my own website, which is more interactive than his. It’s his data, but a better way of visualizing it.</p>

<figure>
  <img src="/assets/images/2026-04-19-study-with-me/FEStudy.png" alt="FE study tool screenshot" style="width: 100%;" />
</figure>

<p>If you’re interested in studying, take a look. I built it for myself but it should be pretty easy for others to pick up.</p>

<p><a href="https://sull1van.com/FEStudy">https://sull1van.com/FEStudy</a></p>]]></content><author><name>Sean Sullivan</name></author><category term="engineering" /><summary type="html"><![CDATA[Hello!]]></summary></entry><entry><title type="html">[PROJECT] A Dozen Chargers in the Lab</title><link href="https://sull1van.com/a-dozen-chargers-in-the-lab.html" rel="alternate" type="text/html" title="[PROJECT] A Dozen Chargers in the Lab" /><published>2026-01-19T00:00:00+00:00</published><updated>2026-01-19T00:00:00+00:00</updated><id>https://sull1van.com/a-dozen-chargers-in-the-lab</id><content type="html" xml:base="https://sull1van.com/a-dozen-chargers-in-the-lab.html"><![CDATA[<h2 id="a-dozen-chargers-in-the-lab-apple-is-okay-but-not-the-best">A Dozen+ Chargers in the Lab: Apple is Okay, but Not the Best</h2>

<figure>
  <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/allchargers.jpg" alt="all chargers" />
  <figcaption> 12 of the ~two dozen we tested</figcaption>
</figure>

<p>Have you ever wondered if there are ‘good’ and ‘bad’ chargers? Is there really a difference between a $5 brick you get at an airport and a $30 one you order direct from a name brand? As it turns out, cheaply made chargers can operate far differently from name-brand ones, and can sometimes be dangerous to use.</p>

<p>This work was done first <a href="https://www.righto.com/2012/10/a-dozen-usb-chargers-in-lab-apple-is.html">by one Google engineer Ken Shirriff</a> many years ago. It was at the top of <a href="https://news.ycombinator.com/">Hacker News</a> at the time, and has been reposted a couple of times. Ken made the case that there is absolutely a difference between the best and worst chargers, and that poorly built chargers have the ability to not only degrade battery life but cause other strange issues like touchscreen glitches.</p>

<p>Fast forward six years and it still looks like there is no real authoritative source that tests big batches of chargers like this. My friend Spencer joined along, being a mechanical engineer, and we started bouncing ideas back and forth until this project eventually came to life. He helped complete a lot of the work below - thank you, Spencer!</p>

<p>Here’s the synopsis of everything below:</p>
<ul>
  <li><strong>GaN chargers are among the best you can buy today, and the marketing around them is real.</strong></li>
  <li><strong>Cheap chargers can also perform well, so the price you pay for a charger doesn’t always correlate to its performance.</strong></li>
  <li><strong>Common brands like Apple generally do test favorably, but some smaller brands actually do better.</strong></li>
  <li><strong>There is an extreme amount of variation even within the third party brands. Some third-party produce both high-quality and extremely low-quality chargers, and you’d have no way of knowing without testing them.</strong></li>
</ul>

<p><br /></p>

<figure>
  <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/ken_ss.png" alt="Ken Shirriff's original charger teardown" />
  <figcaption>Ken Shirriff's original charger teardown article from 2012</figcaption>
</figure>

<hr />

<h2 id="what-we-tested">What we tested</h2>

<p>To get as much out of this project as possible, we tested a lot of chargers. Here’s the full list:</p>
<ul>
  <li>Anker ASPD053a USB C</li>
  <li>Anker 637 Magnetic Charging Station (USB A port and USB C port)</li>
  <li>AOHI GaN 65W AOC-C019</li>
  <li>AOHI GaN 100W AOC-C018</li>
  <li>Amazon Kindle 9W PS57CP</li>
  <li>Dealworthy 20W PYSD-20PCQ-1CU</li>
  <li>SHARGEEK 35W Retro S035U</li>
  <li>Apple HomePod Mini A2305 (Same as Apple 20W Retail charger)</li>
  <li>Apple 30W Retail A2164</li>
  <li>Eero 15W C110011</li>
  <li>Anker 100W A121B GaN Flagship</li>
  <li>Anker Nano 45W A121D GaN Flagship</li>
  <li>Spigen PowerArc ArcStation Pro 30W GaN PE2013UJ</li>
  <li>Apple 96W Retail A2166</li>
  <li>VEBNER 65W PD65U55</li>
  <li>Govee 10W BI12T-050200-BdUU</li>
  <li>Counterfeit AT&amp;T 10W ‘NA010050020’</li>
  <li>Counterfeit Chinese Wall Adapter 10.5W WP2UWR</li>
  <li>Counterfeit Samsung 10W EP-TA20JBE</li>
</ul>

<p>There was also a Macbook Pro M1, an iPhone 17 Pro, and an Anker 621 MAG GO 5000mAh Battery thrown into the mix. These aren’t chargers, so I’ll keep them out of the list above, but they are included in the various results below.</p>

<p>Each charger was tested on several dimensions: <strong>Advertised power versus actual power, power quality, and overcurrent.</strong></p>
<ul>
  <li><strong>Advertised power versus actual power</strong> tells you how well the charger can maintain its intended voltage while putting out maximum current.</li>
  <li><strong>Power quality</strong> means the amount of noise that appears when viewing the charger with an oscilloscope. This noise comes in many forms, but the general idea is that the flatter, the less noise.</li>
  <li><strong>Overcurrent</strong> shows how a charger behaves when a device tries to pull too much current. This is achieved by connecting a charger to an electronic load and having that load request more and more current until the device shuts off. It helps show how well-regulated a charger is, and if it is capable of protecting itself during load.</li>
</ul>

<h2 id="testing-setup">Testing Setup</h2>

<p>Testing USB C chargers is a little complex. Modern chargers rely on the USB C Power Delivery (PD) standard, which generally specifies five voltages they can choose from: 5V, 9V, 12V, 15V, 20V. There are modern variants of this that complicate things even more, such as Programmable Power Supply (PPS) and Adjustable Voltage Supply (AVS), but I won’t get into those. For this project, we only looked at chargers according to the USB C PD spec. USB C PD also specifies that devices should be within +/- 5% of their advertised voltage in order to achieve certification (this is oversimplifying, but the general rule), so we followed that rule when rating them.</p>

<p>With this in mind, our setup consisted of a few different pieces:</p>
<ol>
  <li>An oscilloscope, specifically the Rigol DS1054Z</li>
  <li>An electronic load</li>
  <li>A USB C Power Delivery decoy board</li>
  <li>A voltmeter</li>
  <li>Plenty of electrical wires and extra USB cables</li>
</ol>

<p>The process involved connecting the charger into a power source, and connecting the other end to a USB C Decoy Board, and connecting that decoy board to an electronic load. The oscilloscope probes tapped in right at the decoy board [A1].</p>

<p>The decoy board was needed because the USB C PD Spec needs the load device to choose a voltage. Otherwise the charger won’t send anything. In the chargers Ken tested, most often they’d just send 5V regardless, so this setup was a little more complicated.</p>

<h3 id="a-note-about-resistance">A note about resistance</h3>

<p>One of the things we learned during this project was that resistance could be artificially skewing the measurements. We did a couple of things to minimize this, so it shouldn’t be a big deal.</p>

<details class="note-card">
  <summary>Note</summary>
  <div class="note-card-body">
    To account for this, we ensured each test was conducted with my voltmeter directly connected to the charger's output terminal. If you're interested, the equivalent resistance of the voltmeter during testing was 6.67 mΩ, and the entire system (cable + breakout board + voltmeter) was 170 mΩ. Again, this resistance doesn't apply to any of the numerical measurements we have, since we connected directly to the charger output. However, we are honestly proud how minor this resistance is for a testing setup, considering USB C cables themselves are allowed to carry a resistance of up to 166 mΩ per the USB C PD spec.
  </div>
</details>

<h3 id="rating-system-for-oscilloscope-graphs">Rating system for Oscilloscope graphs</h3>
<p><strong>Noise and Switching Ripple</strong></p>

<p>After conducting the oscilloscope tests, we rated each charger from 1 to 5, using lightning bolts as a visual. These ratings consider two separate factors: overall high-frequency noise (Vpp/spikes) and switching ripple.</p>
<ul>
  <li><strong>Noise</strong> includes the more chaotic high-frequency artifacts, large vertical spikes, and overall ‘fuzziness’ in the output. By measuring the overall peak-to-peak (Vpp) voltage, you can rank the true noise.</li>
  <li>
    <p><strong>Switching Ripple</strong> refers to the high-frequency peaks (e.g., 50KHz, 100KHz) caused by the charger’s internal oscillator continually charging and discharging. This differs from Ken’s methodology, as he used the word <strong>Ripple</strong> specifically to mean the 120Hz line-frequency fluctuations caused by household AC power.</p>
  </li>
  <li><em>Most of the chargers look incredibly dense and ‘thick’ compared to the ones Ken examined. I believe this is because my scope has a memory depth of 24 million points, while the most I saw on Ken’s graphs were around ~50,000 equivalent points of memory depth. I believe the inclusion of this raw high-frequency data at every zoom level is the most honest way to display these chargers.</em></li>
</ul>

<p>For noise, the bolt ratings loosely map to measured peak-to-peak voltage noise on the oscilloscope:</p>

<ul>
  <li>1 bolt: over ~250mV</li>
  <li>2 bolts: under ~250mV</li>
  <li>3 bolts: under ~160mV</li>
  <li>4 bolts: under ~100mV</li>
  <li>5 bolts: under ~80mV</li>
</ul>

<p>These are just general guidelines. I used my judgment for each charger based on everything we could see, including the shape of the waveform and the FFT spectrum, not just the raw mV reading.</p>

<figure style="max-width: 300px;">
  <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/oscilloscope_pic.jpg" alt="Old setup with oscilloscope" style="width: 100%;" />
  <figcaption>My original setup with the oscilloscope (before I started using USB C Decoy boards)</figcaption>
</figure>

<hr />

<h2 id="the-results">The Results</h2>

<p>Scroll through the cards and click any one to expand the full oscilloscope graphs. Each card shows the worst graph that we could reproduce for that charger, assuming typical power usage.</p>
<details class="note-card">
  <summary>Note</summary>
  <div class="note-card-body">
    <ul>
      <li>We learned during testing that all devices showed similar noise profiles at different voltages, so we stuck with lower voltages for these screenshots. Most screenshots below were taken when the charger was giving 9V.</li>
      <li>Within each voltage, we cycled through each charger's range of allowable current, and usually selected the worst graph. If the charger showed noise at the extreme low or high end of current, but no issues for the vast majority of measurements, we'd take the less severe graph. This is because what you're seeing should approximate the noise your device would <em>actually</em> experience during charging, not some hypothetical rating you will never actually see during normal usage.</li>
    </ul>
  </div>
</details>

<h3 id="a-few-more-details-on-noise-and-ripple">A few more details on noise and ripple</h3>

<p>They look confusing at first glance, but you don’t need to be an electrical engineer to understand these next graphs.</p>
<ul>
  <li><strong>Yellow Line (Voltage Trace):</strong> This represents the actual voltage being delivered to your device. The horizontal axis represents time, and the vertical axis represents voltage. In a perfect world, this would be a single, razor-thin, perfectly flat horizontal line. Any deviation from this is an imperfection.</li>
  <li><strong>Purple Line (FFT Spectrum):</strong> You’ll see this purple mountain range near the bottom of many graphs. This is a Fast Fourier Transform (FFT). It takes all the imperfections from the yellow line and sorts them by frequency. A large spike here would mean there is a significant amount of energy at that specific frequency.</li>
  <li><strong>Noise vs. Switching Ripple:</strong> This describes the imperfections on these graphs. It’s important to look at them separately:
    <ul>
      <li><strong>Switching Ripple</strong> is the presence of a main, high-frequency spike (and its harmonics) on the FFT. This is caused by the natural charging and discharging cycle of the charger’s internal circuit. AC Chargers will switch on and off many times per second to effectively create something that is DC current. For that reason, if there’s a significant peak at 90KHz and nowhere else, for instance, we’d say the charger has its primary switching ripple at 90KHz. If the charger has peaks at 90KHz and 180KHz, that is the switching ripple and its harmonic at 180KHz.</li>
    </ul>
  </li>
</ul>

<details class="note-card">
  <summary>Note</summary>
  <div class="note-card-body">
    Ken used the term ripple to mean <strong>Line Ripple</strong>, to describe the lower 120Hz fluctuations caused by the AC wall input; we use Switching Ripple to focus purely on the oscillator.
  </div>
</details>

<ul>
  <li>
    <p><strong>Noise</strong> includes any imperfections on the voltage graph measured in peak-to-peak voltage (Vpp). There are many different kinds of noise, including high-frequency vertical spikes, fuzzy blur, and general jitter. Switching ripple is one component of this.</p>
  </li>
  <li>
    <p><strong>‘Fuzzy’ Blur</strong>: If the yellow line looks incredibly thick or “fuzzy,” it means the charger is constantly shifting its switching speed back and forth (frequency dithering) to dynamically smear its noise.</p>
  </li>
  <li>
    <p><strong>Good vs. Bad:</strong> A high-quality charger produces a thin, flat yellow line with minimal action on the purple FFT graph (ideally just one sharp needle representing its switching ripple). A poor-quality charger will have a thick, fuzzy yellow line (lots of jitter/noise), obvious rolling waves (line ripple), and many aggressive, evenly spaced harmonic spikes on the purple FFT graph (severe switching ripple).</p>
  </li>
</ul>

<h2 id="oscilloscope-graphs">Oscilloscope Graphs</h2>

<style>
  /* Note cards styled globally in the post layout; keep this post's tighter spacing */
  .note-card { margin: 1rem 0; }
  .table-wrapper {
    width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    margin-bottom: 32px;
  }
  .stats-table {
    border-collapse: collapse;
    width: 100%;
    min-width: 600px; /* Force scroll on mobile */
    font-family: sans-serif;
    font-size: calc(1em - 1px);
  }
  .stats-table th, .stats-table td {
    border: 1px solid var(--table-cell-border);
    text-align: left;
    padding: 6px 10px;
  }
  .stats-table th {
    background-color: var(--table-head-bg);
  }
  .usba-badge {
    display: inline-block;
    margin-left: 7px;
    font-size: 0.8em;
    font-weight: 700;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: #555;
    border: 1.5px solid #aaa;
    border-radius: 4px;
    padding: 1px 5px;
    vertical-align: middle;
    white-space: nowrap;
  }
  .stats-table td:nth-child(1),
  .stats-table td:nth-child(2) {
    background-color: rgba(0, 0, 0, 0.03);
  }
  @media (prefers-color-scheme: dark) {
    .stats-table td:nth-child(1),
    .stats-table td:nth-child(2) {
      background-color: rgba(255, 255, 255, 0.04);
    }
    .usba-badge {
      color: var(--muted-fg);
      border-color: #4a4238;
    }
  }
  html[data-theme="dark"] .stats-table td:nth-child(1),
  html[data-theme="dark"] .stats-table td:nth-child(2) { background-color: rgba(255, 255, 255, 0.04); }
  html[data-theme="dark"] .usba-badge { color: var(--muted-fg); border-color: #4a4238; }
  html[data-theme="light"] .stats-table td:nth-child(1),
  html[data-theme="light"] .stats-table td:nth-child(2) { background-color: rgba(0, 0, 0, 0.03); }
  html[data-theme="light"] .usba-badge { color: #555; border-color: #aaa; }
  tr.battery-row { opacity: 0.38; }
</style>

<div class="device-scroller" id="deviceScroller">
  
  <div class="card-column">
    <div class="card-title-above">Macbook Pro M1</div>
    <div class="device-card" style="background: hsl(120, 32%, 93%);">
      <div class="device-content" onclick="openModal({&quot;name&quot;:&quot;Macbook Pro M1&quot;,&quot;img1&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/macbook pro 1.png&quot;,&quot;img2&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/macbook pro 2.png&quot;,&quot;bg&quot;:&quot;hsl(120, 32%, 93%)&quot;,&quot;caption&quot;:&quot;The MacBook Pro had some of the cleanest power of the devices we tested. This is pretty unsurprising since it&#39;s just pulling DC current from its internal battery, and it doesn&#39;t have to chop up AC power like the chargers do.\n\nThere&#39;s also no high frequency switching noise. This makes sense, since it doesn&#39;t have to switch thousands of times a second to step down AC voltage into something manageable.\n&quot;,&quot;rating&quot;:5,&quot;noise_rating&quot;:5,&quot;ripple_rating&quot;:5,&quot;overall_rating&quot;:5,&quot;noise_mv&quot;:24}, this)">
        <div class="device-images">
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/macbook pro 1.png" alt="Macbook Pro M1 1" />
          
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/macbook pro 2.png" alt="Macbook Pro M1 2" />
          
        </div>
        <div class="device-info">
          <div class="device-rating rating-badge-5">
            <span style="text-transform: uppercase; letter-spacing: 0.5px;">Overall rating:</span>
            <span class="bolt-5" style="font-size: 1.2em; line-height: 1;">
              
              ⚡︎⚡︎⚡︎⚡︎⚡︎
            </span>
          </div>
          <figcaption>The MacBook Pro had some of the cleanest power of the devices we tested. This is pretty unsurprising since it's just pulling DC current from its internal battery, and it doesn't have to chop up AC power like the chargers do.

There's also no high frequency switching noise. This makes sense, since it doesn't have to switch thousands of times a second to step down AC voltage into something manageable.</figcaption>
          <button class="expand-btn">Expand</button>
        </div>
      </div>
    </div>
  </div>
  
  <div class="card-column">
    <div class="card-title-above">AOHI GaN 65W Charger</div>
    <div class="device-card" style="background: hsl(120, 32%, 93%);">
      <div class="device-content" onclick="openModal({&quot;name&quot;:&quot;AOHI GaN 65W Charger&quot;,&quot;img1&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/AOHIGaN65W 3.png&quot;,&quot;img2&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/AOHIGaN65W 1.png&quot;,&quot;bg&quot;:&quot;hsl(120, 32%, 93%)&quot;,&quot;caption&quot;:&quot;The best AC power adapter. Very low noise, very low ripple. The only noticeable peak in the FFT is the 125KHz switching frequency. I believe this charger has a new technology in them that allows it to use different switching frequencies depending on how much power is requested, so the switching frequency may change with time. But all in all, the best power supply we saw.\n&quot;,&quot;rating&quot;:5,&quot;noise_rating&quot;:5,&quot;ripple_rating&quot;:5,&quot;overall_rating&quot;:5,&quot;noise_mv&quot;:60}, this)">
        <div class="device-images">
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/AOHIGaN65W 3.png" alt="AOHI GaN 65W Charger 1" />
          
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/AOHIGaN65W 1.png" alt="AOHI GaN 65W Charger 2" />
          
        </div>
        <div class="device-info">
          <div class="device-rating rating-badge-5">
            <span style="text-transform: uppercase; letter-spacing: 0.5px;">Overall rating:</span>
            <span class="bolt-5" style="font-size: 1.2em; line-height: 1;">
              
              ⚡︎⚡︎⚡︎⚡︎⚡︎
            </span>
          </div>
          <figcaption>The best AC power adapter. Very low noise, very low ripple. The only noticeable peak in the FFT is the 125KHz switching frequency. I believe this charger has a new technology in them that allows it to use different switching frequencies depending on how much power is requested, so the switching frequency may change with time. But all in all, the best power supply we saw.</figcaption>
          <button class="expand-btn">Expand</button>
        </div>
      </div>
    </div>
  </div>
  
  <div class="card-column">
    <div class="card-title-above">Anker 621 MAG GO 5000mAh Battery</div>
    <div class="device-card" style="background: hsl(120, 32%, 93%);">
      <div class="device-content" onclick="openModal({&quot;name&quot;:&quot;Anker 621 MAG GO 5000mAh Battery&quot;,&quot;img1&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Anker a1654 Maggo power bank.png&quot;,&quot;img2&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Anker a1654 Maggo power bank 2.png&quot;,&quot;bg&quot;:&quot;hsl(120, 32%, 93%)&quot;,&quot;caption&quot;:&quot;No switching noise or ripple seen here. The one small issue in testing was that it measured 4.74V, just barely under the 4.75V USB limit. The power quality itself is excellent so it stays at a high rating.\n&quot;,&quot;rating&quot;:5,&quot;noise_rating&quot;:5,&quot;ripple_rating&quot;:5,&quot;overall_rating&quot;:5,&quot;noise_mv&quot;:36}, this)">
        <div class="device-images">
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Anker a1654 Maggo power bank.png" alt="Anker 621 MAG GO 5000mAh Battery 1" />
          
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Anker a1654 Maggo power bank 2.png" alt="Anker 621 MAG GO 5000mAh Battery 2" />
          
        </div>
        <div class="device-info">
          <div class="device-rating rating-badge-5">
            <span style="text-transform: uppercase; letter-spacing: 0.5px;">Overall rating:</span>
            <span class="bolt-5" style="font-size: 1.2em; line-height: 1;">
              
              ⚡︎⚡︎⚡︎⚡︎⚡︎
            </span>
          </div>
          <figcaption>No switching noise or ripple seen here. The one small issue in testing was that it measured 4.74V, just barely under the 4.75V USB limit. The power quality itself is excellent so it stays at a high rating.</figcaption>
          <button class="expand-btn">Expand</button>
        </div>
      </div>
    </div>
  </div>
  
  <div class="card-column">
    <div class="card-title-above">Spigen PowerArc ArcStation Pro</div>
    <div class="device-card" style="background: hsl(120, 32%, 93%);">
      <div class="device-content" onclick="openModal({&quot;name&quot;:&quot;Spigen PowerArc ArcStation Pro&quot;,&quot;img1&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Spigen PowerArc 1.png&quot;,&quot;img2&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Spigen PowerArc 2.png&quot;,&quot;bg&quot;:&quot;hsl(120, 32%, 93%)&quot;,&quot;caption&quot;:&quot;We were originally skeptical of this one, but it turned out very well.\n\nThis was marketed as one of the first GaN chargers, having been released sometime back in 2023. It&#39;s using a ~140KHz switching frequency, which seems to be the only source of switching ripple on the 50us graph. I zoomed out and there was a tiny amount of additional noise on the FFT, but not enough to be truly noticeable. The zoomed-out graph looks pretty similar to the one in this image, so I&#39;m just showing the zoomed in one here.\n&quot;,&quot;rating&quot;:5,&quot;noise_rating&quot;:5,&quot;ripple_rating&quot;:5,&quot;overall_rating&quot;:5,&quot;noise_mv&quot;:56}, this)">
        <div class="device-images">
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Spigen PowerArc 1.png" alt="Spigen PowerArc ArcStation Pro 1" />
          
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Spigen PowerArc 2.png" alt="Spigen PowerArc ArcStation Pro 2" />
          
        </div>
        <div class="device-info">
          <div class="device-rating rating-badge-5">
            <span style="text-transform: uppercase; letter-spacing: 0.5px;">Overall rating:</span>
            <span class="bolt-5" style="font-size: 1.2em; line-height: 1;">
              
              ⚡︎⚡︎⚡︎⚡︎⚡︎
            </span>
          </div>
          <figcaption>We were originally skeptical of this one, but it turned out very well.

This was marketed as one of the first GaN chargers, having been released sometime back in 2023. It's using a ~140KHz switching frequency, which seems to be the only source of switching ripple on the 50us graph. I zoomed out and there was a tiny amount of additional noise on the FFT, but not enough to be truly noticeable. The zoomed-out graph looks pretty similar to the one in this image, so I'm just showing the zoomed in one here.</figcaption>
          <button class="expand-btn">Expand</button>
        </div>
      </div>
    </div>
  </div>
  
  <div class="card-column">
    <div class="card-title-above">Eero 15W Charger</div>
    <div class="device-card" style="background: hsl(120, 32%, 93%);">
      <div class="device-content" onclick="openModal({&quot;name&quot;:&quot;Eero 15W Charger&quot;,&quot;img1&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/eero.png&quot;,&quot;img2&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/eero2.png&quot;,&quot;bg&quot;:&quot;hsl(120, 32%, 93%)&quot;,&quot;caption&quot;:&quot;For such a random charger, one that you can&#39;t even purchase yourself, it is surprisingly high quality. It comes included with Eero devices, and looks to be custom-built just for them. Not sure if Amazon/Eero bought this one off the shelf and rebranded it or it&#39;s their own circuit design.\n\nSome switching ripple exists, as you can see on the bottom graph, but it does a great job at filtering out most other noise. It also has a sawtooth waveform, so there is noise, but it is pretty small. \n&quot;,&quot;rating&quot;:4,&quot;noise_rating&quot;:5,&quot;ripple_rating&quot;:3,&quot;overall_rating&quot;:4,&quot;noise_mv&quot;:60}, this)">
        <div class="device-images">
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/eero.png" alt="Eero 15W Charger 1" />
          
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/eero2.png" alt="Eero 15W Charger 2" />
          
        </div>
        <div class="device-info">
          <div class="device-rating rating-badge-4">
            <span style="text-transform: uppercase; letter-spacing: 0.5px;">Overall rating:</span>
            <span class="bolt-4" style="font-size: 1.2em; line-height: 1;">
              
              ⚡︎⚡︎⚡︎⚡︎
            </span>
          </div>
          <figcaption>For such a random charger, one that you can't even purchase yourself, it is surprisingly high quality. It comes included with Eero devices, and looks to be custom-built just for them. Not sure if Amazon/Eero bought this one off the shelf and rebranded it or it's their own circuit design.

Some switching ripple exists, as you can see on the bottom graph, but it does a great job at filtering out most other noise. It also has a sawtooth waveform, so there is noise, but it is pretty small.</figcaption>
          <button class="expand-btn">Expand</button>
        </div>
      </div>
    </div>
  </div>
  
  <div class="card-column">
    <div class="card-title-above">AOHI GaN 100W Charger</div>
    <div class="device-card" style="background: hsl(120, 32%, 93%);">
      <div class="device-content" onclick="openModal({&quot;name&quot;:&quot;AOHI GaN 100W Charger&quot;,&quot;img1&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/AOHIGaN100w 1.png&quot;,&quot;img2&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/AOHIGaN100w 3.png&quot;,&quot;bg&quot;:&quot;hsl(120, 32%, 93%)&quot;,&quot;caption&quot;:&quot;This one performed very well. From our research, this is a GaN charger that uses some components that are so new they have never been used in consumer chargers before. This charger should really be considered a flagship for how much effort they put into it. It&#39;s a little disappointing that the power signature isn&#39;t better. It is good, but for how bleeding-edge this charger is supposed to be, it performs comparably to chargers half its size and price.\n\nThe really cool thing about this charger is that it supports PPS and has the ability to step the voltage in small increments, when needed by the device. We didn&#39;t test this, but it does have that capability.\n\nOne truly interesting thing about this charger was how it managed its voltage. As the current approached the 2-3A range, the voltage actually increased, topping out at 12.36V when I pulled 3A. This is the first charger I tested that dynamically increased its voltage to account for resistance in the charging system.\n&quot;,&quot;rating&quot;:5,&quot;noise_rating&quot;:4,&quot;ripple_rating&quot;:5,&quot;overall_rating&quot;:5,&quot;noise_mv&quot;:72}, this)">
        <div class="device-images">
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/AOHIGaN100w 1.png" alt="AOHI GaN 100W Charger 1" />
          
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/AOHIGaN100w 3.png" alt="AOHI GaN 100W Charger 2" />
          
        </div>
        <div class="device-info">
          <div class="device-rating rating-badge-5">
            <span style="text-transform: uppercase; letter-spacing: 0.5px;">Overall rating:</span>
            <span class="bolt-5" style="font-size: 1.2em; line-height: 1;">
              
              ⚡︎⚡︎⚡︎⚡︎⚡︎
            </span>
          </div>
          <figcaption>This one performed very well. From our research, this is a GaN charger that uses some components that are so new they have never been used in consumer chargers before. This charger should really be considered a flagship for how much effort they put into it. It's a little disappointing that the power signature isn't better. It is good, but for how bleeding-edge this charger is supposed to be, it performs comparably to chargers half its size and price.

The really cool thing about this charger is that it supports PPS and has the ability to step the voltage in small increments, when needed by the device. We didn't test this, but it does have that capability.

One truly interesting thing about this charger was how it managed its voltage. As the current approached the 2-3A range, the voltage actually increased, topping out at 12.36V when I pulled 3A. This is the first charger I tested that dynamically increased its voltage to account for resistance in the charging system.</figcaption>
          <button class="expand-btn">Expand</button>
        </div>
      </div>
    </div>
  </div>
  
  <div class="card-column">
    <div class="card-title-above">Anker 637 Magnetic Charging Station 2 - USB C Port</div>
    <div class="device-card" style="background: hsl(120, 32%, 93%);">
      <div class="device-content" onclick="openModal({&quot;name&quot;:&quot;Anker 637 Magnetic Charging Station 2 - USB C Port&quot;,&quot;img1&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Anker 637 magnetic charging station USB C.png&quot;,&quot;img2&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Anker 637 magnetic charging station USB C 2.png&quot;,&quot;bg&quot;:&quot;hsl(120, 32%, 93%)&quot;,&quot;caption&quot;:&quot;This is a ball-shaped charging station that offers USB A, USB C, and wireless charging outputs. While about 4 years old, it delivers quite clean power. The voltage trace is fairly tight with only minor noise, so nothing alarming.\n\nAs you can tell, it&#39;s only the test of the USB C port. We didn&#39;t bother testing the noise of the USB A port since they sit on the same circuit board (so likely share the same voltage regulation), and also most people will not be using the USB A port on this.\n\nOne other interesting note about this charger: During overcurrent testing, it happily provided far above its rated current. It&#39;s probably because the charger supports\n1) 5v 3a, \n2) 9v 3a, \n3) 12v 3a, \n4) 15v 3a, \n5) 20v 3.25a\n\nAs you can see, it will actually go above 3 A at the highest voltage. They probably just didn&#39;t think anyone would actually use over 3 A at the lower voltages.\n&quot;,&quot;rating&quot;:5,&quot;noise_rating&quot;:5,&quot;ripple_rating&quot;:4,&quot;overall_rating&quot;:5,&quot;noise_mv&quot;:76}, this)">
        <div class="device-images">
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Anker 637 magnetic charging station USB C.png" alt="Anker 637 Magnetic Charging Station 2 - USB C Port 1" />
          
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Anker 637 magnetic charging station USB C 2.png" alt="Anker 637 Magnetic Charging Station 2 - USB C Port 2" />
          
        </div>
        <div class="device-info">
          <div class="device-rating rating-badge-5">
            <span style="text-transform: uppercase; letter-spacing: 0.5px;">Overall rating:</span>
            <span class="bolt-5" style="font-size: 1.2em; line-height: 1;">
              
              ⚡︎⚡︎⚡︎⚡︎⚡︎
            </span>
          </div>
          <figcaption>This is a ball-shaped charging station that offers USB A, USB C, and wireless charging outputs. While about 4 years old, it delivers quite clean power. The voltage trace is fairly tight with only minor noise, so nothing alarming.

As you can tell, it's only the test of the USB C port. We didn't bother testing the noise of the USB A port since they sit on the same circuit board (so likely share the same voltage regulation), and also most people will not be using the USB A port on this.

One other interesting note about this charger: During overcurrent testing, it happily provided far above its rated current. It's probably because the charger supports
1) 5v 3a, 
2) 9v 3a, 
3) 12v 3a, 
4) 15v 3a, 
5) 20v 3.25a

As you can see, it will actually go above 3 A at the highest voltage. They probably just didn't think anyone would actually use over 3 A at the lower voltages.</figcaption>
          <button class="expand-btn">Expand</button>
        </div>
      </div>
    </div>
  </div>
  
  <div class="card-column">
    <div class="card-title-above">Counterfeit Chinese Wall Charger (USB A Only)</div>
    <div class="device-card" style="background: hsl(90, 32%, 93%);">
      <div class="device-content" onclick="openModal({&quot;name&quot;:&quot;Counterfeit Chinese Wall Charger (USB A Only)&quot;,&quot;img1&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Counterfeit chinese outlet 1.png&quot;,&quot;img2&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Counterfeit chinese outlet 2.png&quot;,&quot;bg&quot;:&quot;hsl(90, 32%, 93%)&quot;,&quot;caption&quot;:&quot;This was another charger that tested surprisingly well. It cost less than $10 and has very low high-frequency noise and ripple. There is a bit of high-frequency noise in the 50us graph, but the voltage is pretty stable. The only issue is that it was 0.5V below the 5V threshold during testing, which puts it out of spec for a USB Charger. It gets 1 bolt because of this.&quot;,&quot;rating&quot;:1,&quot;noise_rating&quot;:4,&quot;ripple_rating&quot;:3,&quot;overall_rating&quot;:1,&quot;noise_mv&quot;:84}, this)">
        <div class="device-images">
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Counterfeit chinese outlet 1.png" alt="Counterfeit Chinese Wall Charger (USB A Only) 1" />
          
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Counterfeit chinese outlet 2.png" alt="Counterfeit Chinese Wall Charger (USB A Only) 2" />
          
        </div>
        <div class="device-info">
          <div class="device-rating rating-badge-1">
            <span style="text-transform: uppercase; letter-spacing: 0.5px;">Overall rating:</span>
            <span class="bolt-1" style="font-size: 1.2em; line-height: 1;">
              
              ⚡︎
            </span>
          </div>
          <figcaption>This was another charger that tested surprisingly well. It cost less than $10 and has very low high-frequency noise and ripple. There is a bit of high-frequency noise in the 50us graph, but the voltage is pretty stable. The only issue is that it was 0.5V below the 5V threshold during testing, which puts it out of spec for a USB Charger. It gets 1 bolt because of this.</figcaption>
          <button class="expand-btn">Expand</button>
        </div>
      </div>
    </div>
  </div>
  
  <div class="card-column">
    <div class="card-title-above">Apple 96W Macbook Charger</div>
    <div class="device-card" style="background: hsl(90, 32%, 93%);">
      <div class="device-content" onclick="openModal({&quot;name&quot;:&quot;Apple 96W Macbook Charger&quot;,&quot;img1&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/apple96W3.png&quot;,&quot;img2&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/apple96W2.png&quot;,&quot;bg&quot;:&quot;hsl(90, 32%, 93%)&quot;,&quot;caption&quot;:&quot;Good, but should be better for how expensive this charger is. The total noise is low at 92mV, but there is some noise visible within those intermittent peaks when you go into the lower timeframe. There&#39;s also high-frequency ripple with plenty of harmonics. It also delivered less voltage than advertised, going down to 8.63V when we&#39;d try to pull 3A @ 9V. Overall rating is a 3 because of that high-frequency noise and the voltage sag. Not bad but should be better for $100.&quot;,&quot;rating&quot;:3,&quot;noise_rating&quot;:4,&quot;ripple_rating&quot;:4,&quot;overall_rating&quot;:3,&quot;noise_mv&quot;:92}, this)">
        <div class="device-images">
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/apple96W3.png" alt="Apple 96W Macbook Charger 1" />
          
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/apple96W2.png" alt="Apple 96W Macbook Charger 2" />
          
        </div>
        <div class="device-info">
          <div class="device-rating rating-badge-3">
            <span style="text-transform: uppercase; letter-spacing: 0.5px;">Overall rating:</span>
            <span class="bolt-3" style="font-size: 1.2em; line-height: 1;">
              
              ⚡︎⚡︎⚡︎
            </span>
          </div>
          <figcaption>Good, but should be better for how expensive this charger is. The total noise is low at 92mV, but there is some noise visible within those intermittent peaks when you go into the lower timeframe. There's also high-frequency ripple with plenty of harmonics. It also delivered less voltage than advertised, going down to 8.63V when we'd try to pull 3A @ 9V. Overall rating is a 3 because of that high-frequency noise and the voltage sag. Not bad but should be better for $100.</figcaption>
          <button class="expand-btn">Expand</button>
        </div>
      </div>
    </div>
  </div>
  
  <div class="card-column">
    <div class="card-title-above">Apple 30W Retail Charger</div>
    <div class="device-card" style="background: hsl(90, 32%, 93%);">
      <div class="device-content" onclick="openModal({&quot;name&quot;:&quot;Apple 30W Retail Charger&quot;,&quot;img1&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/apple retail.png&quot;,&quot;img2&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/apple retail 2.png&quot;,&quot;bg&quot;:&quot;hsl(90, 32%, 93%)&quot;,&quot;caption&quot;:&quot;Another decent Apple charger. At 5 W (5V, 1A), it has a pretty messy power signature with a lot of noise, but the voltage graph flattens out to this nice, smooth line at 7.5 W and above. That probably happens because nobody at Apple expected people to use this charger for 5 W of power, being USB C. \n\nWe also tested this 7.5 W in different forms: 5V 1.5A, and also 15V 0.5A. In both 15V and 5V modes, it needed to achieve a grand total of 7.5W before the noise graph smoothed out. so 15V ~0.5A, and 5V ~1.5A. I displayed the 7.5 W+ graph because in normal usage you will almost never encounter that noise, since Apple devices almost always pull more than that during normal charging. \n&quot;,&quot;rating&quot;:4,&quot;noise_rating&quot;:3,&quot;ripple_rating&quot;:3,&quot;overall_rating&quot;:4,&quot;noise_mv&quot;:96}, this)">
        <div class="device-images">
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/apple retail.png" alt="Apple 30W Retail Charger 1" />
          
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/apple retail 2.png" alt="Apple 30W Retail Charger 2" />
          
        </div>
        <div class="device-info">
          <div class="device-rating rating-badge-4">
            <span style="text-transform: uppercase; letter-spacing: 0.5px;">Overall rating:</span>
            <span class="bolt-4" style="font-size: 1.2em; line-height: 1;">
              
              ⚡︎⚡︎⚡︎⚡︎
            </span>
          </div>
          <figcaption>Another decent Apple charger. At 5 W (5V, 1A), it has a pretty messy power signature with a lot of noise, but the voltage graph flattens out to this nice, smooth line at 7.5 W and above. That probably happens because nobody at Apple expected people to use this charger for 5 W of power, being USB C. 

We also tested this 7.5 W in different forms: 5V 1.5A, and also 15V 0.5A. In both 15V and 5V modes, it needed to achieve a grand total of 7.5W before the noise graph smoothed out. so 15V ~0.5A, and 5V ~1.5A. I displayed the 7.5 W+ graph because in normal usage you will almost never encounter that noise, since Apple devices almost always pull more than that during normal charging.</figcaption>
          <button class="expand-btn">Expand</button>
        </div>
      </div>
    </div>
  </div>
  
  <div class="card-column">
    <div class="card-title-above">Anker ASPD053a</div>
    <div class="device-card" style="background: hsl(60, 32%, 93%);">
      <div class="device-content" onclick="openModal({&quot;name&quot;:&quot;Anker ASPD053a&quot;,&quot;img1&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Anker ASP053a 3.png&quot;,&quot;img2&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Anker ASP053a 2.png&quot;,&quot;bg&quot;:&quot;hsl(60, 32%, 93%)&quot;,&quot;caption&quot;:&quot;Not that impressive. The voltage is noticeably noisier than a lot of the other chargers. The frequency spectrum also shows ripple with harmonics at roughly 90KHz intervals.&quot;,&quot;rating&quot;:3,&quot;noise_rating&quot;:3,&quot;ripple_rating&quot;:3,&quot;overall_rating&quot;:3,&quot;noise_mv&quot;:128}, this)">
        <div class="device-images">
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Anker ASP053a 3.png" alt="Anker ASPD053a 1" />
          
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Anker ASP053a 2.png" alt="Anker ASPD053a 2" />
          
        </div>
        <div class="device-info">
          <div class="device-rating rating-badge-3">
            <span style="text-transform: uppercase; letter-spacing: 0.5px;">Overall rating:</span>
            <span class="bolt-3" style="font-size: 1.2em; line-height: 1;">
              
              ⚡︎⚡︎⚡︎
            </span>
          </div>
          <figcaption>Not that impressive. The voltage is noticeably noisier than a lot of the other chargers. The frequency spectrum also shows ripple with harmonics at roughly 90KHz intervals.</figcaption>
          <button class="expand-btn">Expand</button>
        </div>
      </div>
    </div>
  </div>
  
  <div class="card-column">
    <div class="card-title-above">iPhone 17 pro</div>
    <div class="device-card" style="background: hsl(60, 32%, 93%);">
      <div class="device-content" onclick="openModal({&quot;name&quot;:&quot;iPhone 17 pro&quot;,&quot;img1&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/iphone 17 pro.png&quot;,&quot;bg&quot;:&quot;hsl(60, 32%, 93%)&quot;,&quot;caption&quot;:&quot;We gave it 3 bolts to be nice, there&#39;s nothing great about using the iPhone 17&#39;s USB C port as a charger.\n&quot;,&quot;rating&quot;:3,&quot;noise_rating&quot;:3,&quot;ripple_rating&quot;:&quot;N/A&quot;,&quot;overall_rating&quot;:3,&quot;noise_mv&quot;:136}, this)">
        <div class="device-images">
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/iphone 17 pro.png" alt="iPhone 17 pro 1" />
          
          
        </div>
        <div class="device-info">
          <div class="device-rating rating-badge-3">
            <span style="text-transform: uppercase; letter-spacing: 0.5px;">Overall rating:</span>
            <span class="bolt-3" style="font-size: 1.2em; line-height: 1;">
              
              ⚡︎⚡︎⚡︎
            </span>
          </div>
          <figcaption>We gave it 3 bolts to be nice, there's nothing great about using the iPhone 17's USB C port as a charger.</figcaption>
          <button class="expand-btn">Expand</button>
        </div>
      </div>
    </div>
  </div>
  
  <div class="card-column">
    <div class="card-title-above">Shargeek Macintosh Charger</div>
    <div class="device-card" style="background: hsl(60, 32%, 93%);">
      <div class="device-content" onclick="openModal({&quot;name&quot;:&quot;Shargeek Macintosh Charger&quot;,&quot;img1&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Shargeek Fun Macintosh Charger.png&quot;,&quot;img2&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Shargeek Fun Macintosh Charger3.png&quot;,&quot;bg&quot;:&quot;hsl(60, 32%, 93%)&quot;,&quot;caption&quot;:&quot;For being nearly $30, and only rated for 27W, this charger isn&#39;t doing that well. It looks well-regulated in the sense that the waveform is repeatable and standard, but the peaks are so jagged that it is delivering a lot of noise.&quot;,&quot;rating&quot;:3,&quot;noise_rating&quot;:3,&quot;ripple_rating&quot;:3,&quot;overall_rating&quot;:3,&quot;noise_mv&quot;:152}, this)">
        <div class="device-images">
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Shargeek Fun Macintosh Charger.png" alt="Shargeek Macintosh Charger 1" />
          
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Shargeek Fun Macintosh Charger3.png" alt="Shargeek Macintosh Charger 2" />
          
        </div>
        <div class="device-info">
          <div class="device-rating rating-badge-3">
            <span style="text-transform: uppercase; letter-spacing: 0.5px;">Overall rating:</span>
            <span class="bolt-3" style="font-size: 1.2em; line-height: 1;">
              
              ⚡︎⚡︎⚡︎
            </span>
          </div>
          <figcaption>For being nearly $30, and only rated for 27W, this charger isn't doing that well. It looks well-regulated in the sense that the waveform is repeatable and standard, but the peaks are so jagged that it is delivering a lot of noise.</figcaption>
          <button class="expand-btn">Expand</button>
        </div>
      </div>
    </div>
  </div>
  
  <div class="card-column">
    <div class="card-title-above">Govee Power Supply</div>
    <div class="device-card" style="background: hsl(30, 32%, 93%);">
      <div class="device-content" onclick="openModal({&quot;name&quot;:&quot;Govee Power Supply&quot;,&quot;img1&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Govee 3.png&quot;,&quot;img2&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Govee 2.png&quot;,&quot;bg&quot;:&quot;hsl(30, 32%, 93%)&quot;,&quot;caption&quot;:&quot;As expected, not great. This Govee gets two bolts since it delivered roughly what it advertised in terms of voltage and current, but it looks noisy.&quot;,&quot;rating&quot;:2,&quot;noise_rating&quot;:2,&quot;ripple_rating&quot;:2,&quot;overall_rating&quot;:2,&quot;noise_mv&quot;:164}, this)">
        <div class="device-images">
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Govee 3.png" alt="Govee Power Supply 1" />
          
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Govee 2.png" alt="Govee Power Supply 2" />
          
        </div>
        <div class="device-info">
          <div class="device-rating rating-badge-2">
            <span style="text-transform: uppercase; letter-spacing: 0.5px;">Overall rating:</span>
            <span class="bolt-2" style="font-size: 1.2em; line-height: 1;">
              
              ⚡︎⚡︎
            </span>
          </div>
          <figcaption>As expected, not great. This Govee gets two bolts since it delivered roughly what it advertised in terms of voltage and current, but it looks noisy.</figcaption>
          <button class="expand-btn">Expand</button>
        </div>
      </div>
    </div>
  </div>
  
  <div class="card-column">
    <div class="card-title-above">Dealworthy Charger</div>
    <div class="device-card" style="background: hsl(0, 32%, 93%);">
      <div class="device-content" onclick="openModal({&quot;name&quot;:&quot;Dealworthy Charger&quot;,&quot;img1&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Dealworthy 1.png&quot;,&quot;img2&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Dealworthy 3.png&quot;,&quot;bg&quot;:&quot;hsl(0, 32%, 93%)&quot;,&quot;caption&quot;:&quot;Dealworthy is a Target brand, and it&#39;s designed to be low cost. You can see just how cheaply it&#39;s been made by these graphs. Lots of noise, poor regulation, and a lot of switching ripple with harmonics all over the FFT.\n\nAnother interesting thing is that they appear to be smearing the switching frequency by doing some kind of frequency dithering. It&#39;s operating at 40KHz, but we suspect it is going slightly above and below that frequency to spread out the massive amount of noise it makes.\n&quot;,&quot;rating&quot;:1,&quot;noise_rating&quot;:2,&quot;ripple_rating&quot;:2,&quot;overall_rating&quot;:1,&quot;noise_mv&quot;:212}, this)">
        <div class="device-images">
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Dealworthy 1.png" alt="Dealworthy Charger 1" />
          
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Dealworthy 3.png" alt="Dealworthy Charger 2" />
          
        </div>
        <div class="device-info">
          <div class="device-rating rating-badge-1">
            <span style="text-transform: uppercase; letter-spacing: 0.5px;">Overall rating:</span>
            <span class="bolt-1" style="font-size: 1.2em; line-height: 1;">
              
              ⚡︎
            </span>
          </div>
          <figcaption>Dealworthy is a Target brand, and it's designed to be low cost. You can see just how cheaply it's been made by these graphs. Lots of noise, poor regulation, and a lot of switching ripple with harmonics all over the FFT.

Another interesting thing is that they appear to be smearing the switching frequency by doing some kind of frequency dithering. It's operating at 40KHz, but we suspect it is going slightly above and below that frequency to spread out the massive amount of noise it makes.</figcaption>
          <button class="expand-btn">Expand</button>
        </div>
      </div>
    </div>
  </div>
  
  <div class="card-column">
    <div class="card-title-above">Counterfeit AT&amp;T</div>
    <div class="device-card" style="background: hsl(30, 32%, 93%);">
      <div class="device-content" onclick="openModal({&quot;name&quot;:&quot;Counterfeit AT&amp;T&quot;,&quot;img1&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Counterfeit ATnT 1.png&quot;,&quot;img2&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Counterfeit ATnT 2.png&quot;,&quot;bg&quot;:&quot;hsl(30, 32%, 93%)&quot;,&quot;caption&quot;:&quot;Bad. A quick glance on the 5ms timeframe and the voltage almost looks normal, but zooming in reveals a waveform dense with high-frequency noise and severe peaks. There is also meaningful ripple in the lower timeframe. The voltage also measured 5.38V, so it is technically out of the acceptable range for a USB charger. 1 lightning bolt.&quot;,&quot;rating&quot;:1,&quot;noise_rating&quot;:1,&quot;ripple_rating&quot;:2,&quot;overall_rating&quot;:1,&quot;noise_mv&quot;:260}, this)">
        <div class="device-images">
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Counterfeit ATnT 1.png" alt="Counterfeit AT&amp;T 1" />
          
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Counterfeit ATnT 2.png" alt="Counterfeit AT&amp;T 2" />
          
        </div>
        <div class="device-info">
          <div class="device-rating rating-badge-1">
            <span style="text-transform: uppercase; letter-spacing: 0.5px;">Overall rating:</span>
            <span class="bolt-1" style="font-size: 1.2em; line-height: 1;">
              
              ⚡︎
            </span>
          </div>
          <figcaption>Bad. A quick glance on the 5ms timeframe and the voltage almost looks normal, but zooming in reveals a waveform dense with high-frequency noise and severe peaks. There is also meaningful ripple in the lower timeframe. The voltage also measured 5.38V, so it is technically out of the acceptable range for a USB charger. 1 lightning bolt.</figcaption>
          <button class="expand-btn">Expand</button>
        </div>
      </div>
    </div>
  </div>
  
  <div class="card-column">
    <div class="card-title-above">Anker A121B 100W Charger</div>
    <div class="device-card" style="background: hsl(0, 32%, 93%);">
      <div class="device-content" onclick="openModal({&quot;name&quot;:&quot;Anker A121B 100W Charger&quot;,&quot;img1&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Anker A121B 100w 1.png&quot;,&quot;img2&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Anker A121B 100w 2.png&quot;,&quot;bg&quot;:&quot;hsl(0, 32%, 93%)&quot;,&quot;caption&quot;:&quot;This is a \&quot;GaN\&quot; flagship charger released by anker sometime in late 2025. \n\nIt&#39;s better than its 45W cousin (the Anker A121D), but this charger isn&#39;t that great. It does push out the advertised voltage and current, but it does so with a wall of noise. Zooming in to the smaller timeframe shows voltage peaks every few microseconds. What a strange design from Anker, who claim this to be a GaN charger. It is clearly not made well.\n&quot;,&quot;rating&quot;:2,&quot;noise_rating&quot;:2,&quot;ripple_rating&quot;:2,&quot;overall_rating&quot;:2,&quot;noise_mv&quot;:200}, this)">
        <div class="device-images">
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Anker A121B 100w 1.png" alt="Anker A121B 100W Charger 1" />
          
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Anker A121B 100w 2.png" alt="Anker A121B 100W Charger 2" />
          
        </div>
        <div class="device-info">
          <div class="device-rating rating-badge-2">
            <span style="text-transform: uppercase; letter-spacing: 0.5px;">Overall rating:</span>
            <span class="bolt-2" style="font-size: 1.2em; line-height: 1;">
              
              ⚡︎⚡︎
            </span>
          </div>
          <figcaption>This is a "GaN" flagship charger released by anker sometime in late 2025. 

It's better than its 45W cousin (the Anker A121D), but this charger isn't that great. It does push out the advertised voltage and current, but it does so with a wall of noise. Zooming in to the smaller timeframe shows voltage peaks every few microseconds. What a strange design from Anker, who claim this to be a GaN charger. It is clearly not made well.</figcaption>
          <button class="expand-btn">Expand</button>
        </div>
      </div>
    </div>
  </div>
  
  <div class="card-column">
    <div class="card-title-above">Amazon Kindle Charger</div>
    <div class="device-card" style="background: hsl(0, 32%, 93%);">
      <div class="device-content" onclick="openModal({&quot;name&quot;:&quot;Amazon Kindle Charger&quot;,&quot;img1&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Amazon 1.png&quot;,&quot;img2&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Amazon kindle 2.png&quot;,&quot;bg&quot;:&quot;hsl(0, 32%, 93%)&quot;,&quot;caption&quot;:&quot;Another awful charger. Considering this comes as the standard Kindle charger, it is a poor showing from Amazon. The voltage is wide and noisy, with a chaotic high-frequency spectrum. It also measured 5.30V, well above the 5.25V USB ceiling and therefore out of spec for a USB charger. If the graphs weren&#39;t bad enough, the bad voltage would give it 1 bolt.&quot;,&quot;rating&quot;:1,&quot;noise_rating&quot;:1,&quot;ripple_rating&quot;:2,&quot;overall_rating&quot;:1,&quot;noise_mv&quot;:288}, this)">
        <div class="device-images">
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Amazon 1.png" alt="Amazon Kindle Charger 1" />
          
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Amazon kindle 2.png" alt="Amazon Kindle Charger 2" />
          
        </div>
        <div class="device-info">
          <div class="device-rating rating-badge-1">
            <span style="text-transform: uppercase; letter-spacing: 0.5px;">Overall rating:</span>
            <span class="bolt-1" style="font-size: 1.2em; line-height: 1;">
              
              ⚡︎
            </span>
          </div>
          <figcaption>Another awful charger. Considering this comes as the standard Kindle charger, it is a poor showing from Amazon. The voltage is wide and noisy, with a chaotic high-frequency spectrum. It also measured 5.30V, well above the 5.25V USB ceiling and therefore out of spec for a USB charger. If the graphs weren't bad enough, the bad voltage would give it 1 bolt.</figcaption>
          <button class="expand-btn">Expand</button>
        </div>
      </div>
    </div>
  </div>
  
  <div class="card-column">
    <div class="card-title-above">Apple HomePod Mini Charger</div>
    <div class="device-card" style="background: hsl(0, 32%, 93%);">
      <div class="device-content" onclick="openModal({&quot;name&quot;:&quot;Apple HomePod Mini Charger&quot;,&quot;img1&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Apple Homepod Mini.png&quot;,&quot;img2&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Apple Homepod Mini 2.png&quot;,&quot;bg&quot;:&quot;hsl(0, 32%, 93%)&quot;,&quot;caption&quot;:&quot;Disappointing, especially given that this ships directly from Apple. The voltage is thick and irregular, and shows signs of both low-frequency and high-frequency ripple at a glance. On the bottom of the screen, the frequency spectrum shows elevated noise across the board. Its noise is at 308mV peak-to-peak and it ranks among the worst chargers in this entire test. \n\nThis test was surprising. We also happened to have two of these chargers, one from a HomePod and one from an iPhone of years past. This charger is actually the same as the Apple 20W [you can buy directly from their website](https://www.apple.com/shop/product/mwvv3am/a/20w-usb-c-power-adapter). And while you could, I have no idea why you would want to. $20 can get you a much better charger than this.\n&quot;,&quot;rating&quot;:1,&quot;noise_rating&quot;:1,&quot;ripple_rating&quot;:2,&quot;overall_rating&quot;:1,&quot;noise_mv&quot;:308}, this)">
        <div class="device-images">
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Apple Homepod Mini.png" alt="Apple HomePod Mini Charger 1" />
          
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Apple Homepod Mini 2.png" alt="Apple HomePod Mini Charger 2" />
          
        </div>
        <div class="device-info">
          <div class="device-rating rating-badge-1">
            <span style="text-transform: uppercase; letter-spacing: 0.5px;">Overall rating:</span>
            <span class="bolt-1" style="font-size: 1.2em; line-height: 1;">
              
              ⚡︎
            </span>
          </div>
          <figcaption>Disappointing, especially given that this ships directly from Apple. The voltage is thick and irregular, and shows signs of both low-frequency and high-frequency ripple at a glance. On the bottom of the screen, the frequency spectrum shows elevated noise across the board. Its noise is at 308mV peak-to-peak and it ranks among the worst chargers in this entire test. 

This test was surprising. We also happened to have two of these chargers, one from a HomePod and one from an iPhone of years past. This charger is actually the same as the Apple 20W [you can buy directly from their website](https://www.apple.com/shop/product/mwvv3am/a/20w-usb-c-power-adapter). And while you could, I have no idea why you would want to. $20 can get you a much better charger than this.</figcaption>
          <button class="expand-btn">Expand</button>
        </div>
      </div>
    </div>
  </div>
  
  <div class="card-column">
    <div class="card-title-above">Vebner GaN 65W Charger</div>
    <div class="device-card" style="background: hsl(0, 32%, 93%);">
      <div class="device-content" onclick="openModal({&quot;name&quot;:&quot;Vebner GaN 65W Charger&quot;,&quot;img1&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/VEBNERgan.png&quot;,&quot;img2&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/VEBNERgan2.png&quot;,&quot;bg&quot;:&quot;hsl(0, 32%, 93%)&quot;,&quot;caption&quot;:&quot;Being marketed as a GaN charger, this is another disappointment. The voltage has a lot of noise, 332mV of it, and the frequency spectrum is elevated across the board. The voltage looks a little more concentrated than it does on the Apple HomePod Mini chart, suggesting to me that this charger might actually be a little better. But in terms of absolute noise, it&#39;s worse. \n&quot;,&quot;rating&quot;:1,&quot;noise_rating&quot;:1,&quot;ripple_rating&quot;:1,&quot;overall_rating&quot;:1,&quot;noise_mv&quot;:332}, this)">
        <div class="device-images">
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/VEBNERgan.png" alt="Vebner GaN 65W Charger 1" />
          
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/VEBNERgan2.png" alt="Vebner GaN 65W Charger 2" />
          
        </div>
        <div class="device-info">
          <div class="device-rating rating-badge-1">
            <span style="text-transform: uppercase; letter-spacing: 0.5px;">Overall rating:</span>
            <span class="bolt-1" style="font-size: 1.2em; line-height: 1;">
              
              ⚡︎
            </span>
          </div>
          <figcaption>Being marketed as a GaN charger, this is another disappointment. The voltage has a lot of noise, 332mV of it, and the frequency spectrum is elevated across the board. The voltage looks a little more concentrated than it does on the Apple HomePod Mini chart, suggesting to me that this charger might actually be a little better. But in terms of absolute noise, it's worse.</figcaption>
          <button class="expand-btn">Expand</button>
        </div>
      </div>
    </div>
  </div>
  
  <div class="card-column">
    <div class="card-title-above">Anker A121D 45W iPhone 17 charger</div>
    <div class="device-card" style="background: hsl(0, 32%, 93%);">
      <div class="device-content" onclick="openModal({&quot;name&quot;:&quot;Anker A121D 45W iPhone 17 charger&quot;,&quot;img1&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Anker A121D 45w iPhone 17 charger 1.png&quot;,&quot;img2&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Anker A121D 45w iPhone 17 charger 3.png&quot;,&quot;bg&quot;:&quot;hsl(0, 32%, 93%)&quot;,&quot;caption&quot;:&quot;Is this even GaN???\n\nEasily the most disappointing charger of the bunch. Anker just released this (late 2025) and couldn&#39;t help themselves from marketing just how great it was.\n\nThe only good thing about this charger is that it outputs its advertised voltage and current. Aside from that, it&#39;s awful. Noise everywhere, and constant high-voltage spikes that you can see in the lower timeframe. Also, at that lower timeframe, it&#39;s unclear what the charger is actually doing. It seems to be constantly sending out various voltages, somewhat resembling a sawtooth but also just resembling noise. \n\n&lt;em&gt;Sidenote: you might point out that earlier we mentioned the AOHI GaN chargers have the ability to change their switching frequency as needed. You may be saying, how is that any different from what you are saying Anker did here? It&#39;s a valid question. The difference is that Anker clearly had too much noise at the switching frequency of the charger, at ~90KHz, and they needed to spread that noise out. So they employ a variable switching frequency but only vary it by 20-50KHz. Constantly moving the switching frequency up and down, so the noise doesn&#39;t make any one peak so high that it fails regulatory testing. On the other hand, AOHI has no noise to begin with, so when they change the switching frequency, it&#39;s only happening once (I suspect only when the requested voltage changes). They don&#39;t need to constantly switch up and down, because their aim is not to spread the noise out. &lt;/em&gt;\n&quot;,&quot;rating&quot;:1,&quot;noise_rating&quot;:1,&quot;ripple_rating&quot;:2,&quot;overall_rating&quot;:1,&quot;noise_mv&quot;:244}, this)">
        <div class="device-images">
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Anker A121D 45w iPhone 17 charger 1.png" alt="Anker A121D 45W iPhone 17 charger 1" />
          
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Anker A121D 45w iPhone 17 charger 3.png" alt="Anker A121D 45W iPhone 17 charger 2" />
          
        </div>
        <div class="device-info">
          <div class="device-rating rating-badge-1">
            <span style="text-transform: uppercase; letter-spacing: 0.5px;">Overall rating:</span>
            <span class="bolt-1" style="font-size: 1.2em; line-height: 1;">
              
              ⚡︎
            </span>
          </div>
          <figcaption>Is this even GaN???

Easily the most disappointing charger of the bunch. Anker just released this (late 2025) and couldn't help themselves from marketing just how great it was.

The only good thing about this charger is that it outputs its advertised voltage and current. Aside from that, it's awful. Noise everywhere, and constant high-voltage spikes that you can see in the lower timeframe. Also, at that lower timeframe, it's unclear what the charger is actually doing. It seems to be constantly sending out various voltages, somewhat resembling a sawtooth but also just resembling noise. 

<em>Sidenote: you might point out that earlier we mentioned the AOHI GaN chargers have the ability to change their switching frequency as needed. You may be saying, how is that any different from what you are saying Anker did here? It's a valid question. The difference is that Anker clearly had too much noise at the switching frequency of the charger, at ~90KHz, and they needed to spread that noise out. So they employ a variable switching frequency but only vary it by 20-50KHz. Constantly moving the switching frequency up and down, so the noise doesn't make any one peak so high that it fails regulatory testing. On the other hand, AOHI has no noise to begin with, so when they change the switching frequency, it's only happening once (I suspect only when the requested voltage changes). They don't need to constantly switch up and down, because their aim is not to spread the noise out. </em></figcaption>
          <button class="expand-btn">Expand</button>
        </div>
      </div>
    </div>
  </div>
  
  <div class="card-column">
    <div class="card-title-above">Counterfeit Samsung</div>
    <div class="device-card" style="background: hsl(0, 32%, 93%);">
      <div class="device-content" onclick="openModal({&quot;name&quot;:&quot;Counterfeit Samsung&quot;,&quot;img1&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Counterfeit Samsung 3.png&quot;,&quot;img2&quot;:&quot;/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Counterfeit Samsung 1.png&quot;,&quot;bg&quot;:&quot;hsl(0, 32%, 93%)&quot;,&quot;caption&quot;:&quot;The worst one of the bunch, but that would be expected with a counterfeit charger. The original researcher (Ken Shirriff) doubled his scale to show the graph of his worst charger, but we wanted to evaluate all the chargers on the same scale, so you can see how bad some of these really are. On this image, it&#39;s tough to figure out what this charger is even trying to do. It provided 4.4V when 5V was requested, so it doesn&#39;t even pass USB spec.\n\nAnother issue was overcurrent. This charger allowed the current to rise nearly 1A past its rated upper limit. This 10W charger was pumping out nearly 14W before it finally shut off. None of the other chargers did this.\n&quot;,&quot;rating&quot;:1,&quot;noise_rating&quot;:1,&quot;ripple_rating&quot;:1,&quot;overall_rating&quot;:1,&quot;noise_mv&quot;:468}, this)">
        <div class="device-images">
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Counterfeit Samsung 3.png" alt="Counterfeit Samsung 1" />
          
          
          <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/Counterfeit Samsung 1.png" alt="Counterfeit Samsung 2" />
          
        </div>
        <div class="device-info">
          <div class="device-rating rating-badge-1">
            <span style="text-transform: uppercase; letter-spacing: 0.5px;">Overall rating:</span>
            <span class="bolt-1" style="font-size: 1.2em; line-height: 1;">
              
              ⚡︎
            </span>
          </div>
          <figcaption>The worst one of the bunch, but that would be expected with a counterfeit charger. The original researcher (Ken Shirriff) doubled his scale to show the graph of his worst charger, but we wanted to evaluate all the chargers on the same scale, so you can see how bad some of these really are. On this image, it's tough to figure out what this charger is even trying to do. It provided 4.4V when 5V was requested, so it doesn't even pass USB spec.

Another issue was overcurrent. This charger allowed the current to rise nearly 1A past its rated upper limit. This 10W charger was pumping out nearly 14W before it finally shut off. None of the other chargers did this.</figcaption>
          <button class="expand-btn">Expand</button>
        </div>
      </div>
    </div>
  </div>
  
</div>

<div class="custom-scroll-area">
  <div class="custom-scroll-track" id="customTrack">
    <div class="custom-scroll-thumb" id="customThumb"></div>
  </div>
</div>
<div class="quality-labels-bar">
  <span>←← BETTER</span>
  <span>WORSE →→</span>
</div>

<div id="device-modal" onclick="closeModal()">
  <span class="modal-dismiss-hint bottom">click anywhere to dismiss</span>
  <div class="modal-wrapper" onclick="event.stopPropagation()">
    <div class="modal-header">
      <div id="modal-title" class="modal-title"></div>
      <button class="modal-close-btn" onclick="closeModal()" aria-label="Close modal">✕</button>
    </div>
    <div class="modal-container">
      <div id="modal-content" class="modal-body">
        <!-- Content injected by JS -->
      </div>
    </div>
  </div>
</div>

<script>
  function openModal(item, triggerBtn) {
    const modal = document.getElementById('device-modal');
    const content = document.getElementById('modal-content');

    let imgsHtml = '';
    if(item.img1) imgsHtml += `<a href="${item.img1}" target="_blank" style="display:flex; flex:1; min-height:0;"><img src="${item.img1}" alt="${item.name}"></a>`;
    if(item.img2) imgsHtml += `<a href="${item.img2}" target="_blank" style="display:flex; flex:1; min-height:0;"><img src="${item.img2}" alt="${item.name}"></a>`;

    document.getElementById('modal-title').textContent = item.name;

    const getBolts = (rating) => {
      if (rating === 'N/A' || rating === undefined || rating === null) return '<span style="color:#666; font-weight:700;">N/A</span>';
      let b = '';
      for (let i = 0; i < rating; i++) b += '⚡︎';
      return `<span class="bolt-${rating}" style="font-size: 1.3em;">${b}</span>`;
    };

    const noiseBolts = getBolts(item.noise_rating);
    const rippleBolts = getBolts(item.ripple_rating);
    const overallBolts = getBolts(item.overall_rating);

    content.innerHTML = `
      <div class="modal-imgs">${imgsHtml}</div>
      <div class="modal-text-panel">
        <div class="modal-ratings-summary">
          <div class="rating-item"><span class="label">Noise:</span> ${noiseBolts}</div>
          <div class="rating-item"><span class="label">Ripple:</span> ${rippleBolts}</div>
          <div class="rating-item"><span class="label">Overall:</span> ${overallBolts}</div>
        </div>
        <p>${(item.caption || '').trim()}</p>
      </div>
      <button class="modal-close-bottom" onclick="closeModal()">CLOSE</button>
    `;

    // Set transform-origin to the card's position so it appears to grow from there
    const card = triggerBtn.closest('.device-card');
    if (card) {
      const rect = card.getBoundingClientRect();
      const originX = rect.left + rect.width / 2;
      const originY = rect.top + rect.height / 2;
      const container = modal.querySelector('.modal-container');
      container.style.transformOrigin = `${originX}px ${originY}px`;
    }

    modal.style.display = 'flex';
    document.body.style.overflow = 'hidden';

    // Trigger animation on next frame
    requestAnimationFrame(() => {
      requestAnimationFrame(() => {
        modal.classList.add('modal-open');
      });
    });
  }

  function closeModal() {
    const modal = document.getElementById('device-modal');
    modal.classList.remove('modal-open');
    // Wait for transition to finish before hiding
    setTimeout(() => {
      modal.style.display = 'none';
      document.body.style.overflow = 'auto';
    }, 350);
  }

  // Close on Escape key
  document.addEventListener('keydown', (e) => {
    if (e.key === 'Escape') closeModal();
  });

  // Backdrop hover: turn red when mouse is over the bare backdrop, not the modal content
  const modalEl = document.getElementById('device-modal');
  modalEl.addEventListener('mousemove', (e) => {
    const wrapper = modalEl.querySelector('.modal-wrapper');
    if (wrapper && wrapper.contains(e.target)) {
      modalEl.classList.remove('modal-danger');
    } else {
      modalEl.classList.add('modal-danger');
    }
  });
  modalEl.addEventListener('mouseleave', () => {
    modalEl.classList.remove('modal-danger');
  });

  // ─── Custom Scrollbar Sync ───
  (function() {
    const scroller = document.getElementById('deviceScroller');
    const track = document.getElementById('customTrack');
    const thumb = document.getElementById('customThumb');
    if (!scroller || !track || !thumb) return;

    function updateThumb() {
      const scrollableWidth = scroller.scrollWidth - scroller.clientWidth;
      if (scrollableWidth <= 0) {
        thumb.style.display = 'none';
        return;
      }
      thumb.style.display = 'block';
      const trackWidth = track.clientWidth;
      const thumbWidth = Math.max(60, (scroller.clientWidth / scroller.scrollWidth) * trackWidth);
      const scrollPercent = scroller.scrollLeft / scrollableWidth;
      const maxThumbLeft = trackWidth - thumbWidth;
      thumb.style.width = thumbWidth + 'px';
      thumb.style.left = (scrollPercent * maxThumbLeft) + 'px';
    }

    scroller.addEventListener('scroll', updateThumb);
    window.addEventListener('resize', updateThumb);

    // Drag support
    let isDragging = false;
    let dragStartX = 0;
    let dragStartLeft = 0;

    thumb.addEventListener('mousedown', (e) => {
      isDragging = true;
      dragStartX = e.clientX;
      dragStartLeft = parseFloat(thumb.style.left) || 0;
      document.body.style.userSelect = 'none';
      document.body.style.cursor = 'grabbing';
      e.preventDefault();
    });

    document.addEventListener('mousemove', (e) => {
      if (!isDragging) return;
      const dx = e.clientX - dragStartX;
      const trackWidth = track.clientWidth;
      const thumbWidth = thumb.clientWidth;
      const maxThumbLeft = trackWidth - thumbWidth;
      const newLeft = Math.max(0, Math.min(maxThumbLeft, dragStartLeft + dx));
      const scrollPercent = newLeft / maxThumbLeft;
      const scrollableWidth = scroller.scrollWidth - scroller.clientWidth;
      scroller.scrollLeft = scrollPercent * scrollableWidth;
    });

    document.addEventListener('mouseup', () => {
      if (isDragging) {
        isDragging = false;
        document.body.style.userSelect = '';
        document.body.style.cursor = '';
      }
    });

    // Click on track to jump
    track.addEventListener('click', (e) => {
      if (e.target === thumb) return;
      const rect = track.getBoundingClientRect();
      const clickX = e.clientX - rect.left;
      const trackWidth = track.clientWidth;
      const thumbWidth = thumb.clientWidth;
      const targetLeft = clickX - thumbWidth / 2;
      const maxThumbLeft = trackWidth - thumbWidth;
      const scrollPercent = Math.max(0, Math.min(1, targetLeft / maxThumbLeft));
      const scrollableWidth = scroller.scrollWidth - scroller.clientWidth;
      scroller.scrollLeft = scrollPercent * scrollableWidth;
    });

    // Touch drag support
    thumb.addEventListener('touchstart', (e) => {
      isDragging = true;
      dragStartX = e.touches[0].clientX;
      dragStartLeft = parseFloat(thumb.style.left) || 0;
      e.preventDefault();
    }, { passive: false });

    document.addEventListener('touchmove', (e) => {
      if (!isDragging) return;
      const dx = e.touches[0].clientX - dragStartX;
      const trackWidth = track.clientWidth;
      const thumbWidth = thumb.clientWidth;
      const maxThumbLeft = trackWidth - thumbWidth;
      const newLeft = Math.max(0, Math.min(maxThumbLeft, dragStartLeft + dx));
      const scrollPercent = newLeft / maxThumbLeft;
      const scrollableWidth = scroller.scrollWidth - scroller.clientWidth;
      scroller.scrollLeft = scrollPercent * scrollableWidth;
    }, { passive: true });

    document.addEventListener('touchend', () => {
      isDragging = false;
    });

    // Initial render
    setTimeout(updateThumb, 100);
    // Also update after images load
    scroller.querySelectorAll('img').forEach(img => {
      img.addEventListener('load', updateThumb);
    });
  })();
</script>

<p><br /></p>

<h3 id="oscilloscope-graphs---results-table">Oscilloscope Graphs - Results Table</h3>

<p>The DC items in here, like the Macbook Pro, are colored in grey to avoid conflating them with the AC chargers. They’re just included here for reference.</p>

<div class="table-wrapper">
<table>
  <thead>
    <tr>
      <th>Charger</th>
      <th>Noise in mV</th>
      <th>Noise Rating (Vpp and Spikes)</th>
      <th>Switching Ripple Rating (FFT Harmonics)</th>
    </tr>
  </thead>
  <tbody>
    
    
      
      
      

      
      
      

      <tr class="battery-row">
        <td><strong>Macbook Pro M1</strong></td>
        <td>24mV</td>
        <td>
          <span class="bolt-5">
            &#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;
          </span>
        </td>
        <td>
          
            <span class="bolt-5">
              &#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;
            </span>
          
        </td>
      </tr>
    
      
      
      

      
      
      

      <tr class="battery-row">
        <td><strong>Anker 621 MAG GO 5000mAh Battery</strong></td>
        <td>36mV</td>
        <td>
          <span class="bolt-5">
            &#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;
          </span>
        </td>
        <td>
          
            <span class="bolt-5">
              &#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;
            </span>
          
        </td>
      </tr>
    
      
      
      

      
      
      

      <tr>
        <td><strong>Spigen PowerArc ArcStation Pro</strong></td>
        <td>56mV</td>
        <td>
          <span class="bolt-5">
            &#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;
          </span>
        </td>
        <td>
          
            <span class="bolt-5">
              &#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;
            </span>
          
        </td>
      </tr>
    
      
      
      

      
      
      

      <tr>
        <td><strong>AOHI GaN 65W Charger</strong></td>
        <td>60mV</td>
        <td>
          <span class="bolt-5">
            &#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;
          </span>
        </td>
        <td>
          
            <span class="bolt-5">
              &#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;
            </span>
          
        </td>
      </tr>
    
      
      
      

      
      
      

      <tr>
        <td><strong>Eero 15W Charger</strong></td>
        <td>60mV</td>
        <td>
          <span class="bolt-5">
            &#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;
          </span>
        </td>
        <td>
          
            <span class="bolt-3">
              &#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;
            </span>
          
        </td>
      </tr>
    
      
      
      

      
      
      

      <tr>
        <td><strong>AOHI GaN 100W Charger</strong></td>
        <td>72mV</td>
        <td>
          <span class="bolt-4">
            &#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;
          </span>
        </td>
        <td>
          
            <span class="bolt-5">
              &#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;
            </span>
          
        </td>
      </tr>
    
      
      
      

      
      
      

      <tr>
        <td><strong>Anker 637 Magnetic Charging Station 2 - USB C</strong></td>
        <td>76mV</td>
        <td>
          <span class="bolt-5">
            &#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;
          </span>
        </td>
        <td>
          
            <span class="bolt-4">
              &#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;
            </span>
          
        </td>
      </tr>
    
      
      
      

      
      
      

      <tr>
        <td><strong>Counterfeit Chinese Wall Charger</strong><span class="usba-badge">USB A Only</span></td>
        <td>84mV</td>
        <td>
          <span class="bolt-4">
            &#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;
          </span>
        </td>
        <td>
          
            <span class="bolt-3">
              &#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;
            </span>
          
        </td>
      </tr>
    
      
      
      

      
      
      

      <tr>
        <td><strong>Apple 96W Macbook Charger</strong></td>
        <td>92mV</td>
        <td>
          <span class="bolt-4">
            &#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;
          </span>
        </td>
        <td>
          
            <span class="bolt-4">
              &#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;
            </span>
          
        </td>
      </tr>
    
      
      
      

      
      
      

      <tr>
        <td><strong>Apple 30W Retail Charger</strong></td>
        <td>96mV</td>
        <td>
          <span class="bolt-3">
            &#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;
          </span>
        </td>
        <td>
          
            <span class="bolt-3">
              &#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;
            </span>
          
        </td>
      </tr>
    
      
      
      

      
      
      

      <tr>
        <td><strong>Anker ASPD053a</strong></td>
        <td>128mV</td>
        <td>
          <span class="bolt-3">
            &#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;
          </span>
        </td>
        <td>
          
            <span class="bolt-3">
              &#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;
            </span>
          
        </td>
      </tr>
    
      
      
      

      
      
      

      <tr class="battery-row">
        <td><strong>iPhone 17 pro</strong></td>
        <td>136mV</td>
        <td>
          <span class="bolt-3">
            &#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;
          </span>
        </td>
        <td>
          
            N/A
          
        </td>
      </tr>
    
      
      
      

      
      
      

      <tr>
        <td><strong>Shargeek Macintosh Charger</strong></td>
        <td>152mV</td>
        <td>
          <span class="bolt-3">
            &#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;
          </span>
        </td>
        <td>
          
            <span class="bolt-3">
              &#x26A1;&#xFE0E;&#x26A1;&#xFE0E;&#x26A1;&#xFE0E;
            </span>
          
        </td>
      </tr>
    
      
      
      

      
      
      

      <tr>
        <td><strong>Govee Power Supply</strong></td>
        <td>164mV</td>
        <td>
          <span class="bolt-2">
            &#x26A1;&#xFE0E;&#x26A1;&#xFE0E;
          </span>
        </td>
        <td>
          
            <span class="bolt-2">
              &#x26A1;&#xFE0E;&#x26A1;&#xFE0E;
            </span>
          
        </td>
      </tr>
    
      
      
      

      
      
      

      <tr>
        <td><strong>Anker A121B 100W Charger</strong></td>
        <td>200mV</td>
        <td>
          <span class="bolt-2">
            &#x26A1;&#xFE0E;&#x26A1;&#xFE0E;
          </span>
        </td>
        <td>
          
            <span class="bolt-2">
              &#x26A1;&#xFE0E;&#x26A1;&#xFE0E;
            </span>
          
        </td>
      </tr>
    
      
      
      

      
      
      

      <tr>
        <td><strong>Dealworthy Charger</strong></td>
        <td>212mV</td>
        <td>
          <span class="bolt-2">
            &#x26A1;&#xFE0E;&#x26A1;&#xFE0E;
          </span>
        </td>
        <td>
          
            <span class="bolt-2">
              &#x26A1;&#xFE0E;&#x26A1;&#xFE0E;
            </span>
          
        </td>
      </tr>
    
      
      
      

      
      
      

      <tr class="battery-row">
        <td><strong>Anker A121D 45W iPhone 17 charger</strong></td>
        <td>244mV</td>
        <td>
          <span class="bolt-1">
            &#x26A1;&#xFE0E;
          </span>
        </td>
        <td>
          
            <span class="bolt-2">
              &#x26A1;&#xFE0E;&#x26A1;&#xFE0E;
            </span>
          
        </td>
      </tr>
    
      
      
      

      
      
      

      <tr>
        <td><strong>Counterfeit AT&amp;T</strong></td>
        <td>260mV</td>
        <td>
          <span class="bolt-1">
            &#x26A1;&#xFE0E;
          </span>
        </td>
        <td>
          
            <span class="bolt-2">
              &#x26A1;&#xFE0E;&#x26A1;&#xFE0E;
            </span>
          
        </td>
      </tr>
    
      
      
      

      
      
      

      <tr>
        <td><strong>Amazon Kindle Charger</strong></td>
        <td>288mV</td>
        <td>
          <span class="bolt-1">
            &#x26A1;&#xFE0E;
          </span>
        </td>
        <td>
          
            <span class="bolt-2">
              &#x26A1;&#xFE0E;&#x26A1;&#xFE0E;
            </span>
          
        </td>
      </tr>
    
      
      
      

      
      
      

      <tr>
        <td><strong>Apple HomePod Mini Charger</strong></td>
        <td>308mV</td>
        <td>
          <span class="bolt-1">
            &#x26A1;&#xFE0E;
          </span>
        </td>
        <td>
          
            <span class="bolt-2">
              &#x26A1;&#xFE0E;&#x26A1;&#xFE0E;
            </span>
          
        </td>
      </tr>
    
      
      
      

      
      
      

      <tr>
        <td><strong>Vebner GaN 65W Charger</strong></td>
        <td>332mV</td>
        <td>
          <span class="bolt-1">
            &#x26A1;&#xFE0E;
          </span>
        </td>
        <td>
          
            <span class="bolt-1">
              &#x26A1;&#xFE0E;
            </span>
          
        </td>
      </tr>
    
      
      
      

      
      
      

      <tr>
        <td><strong>Counterfeit Samsung</strong></td>
        <td>468mV</td>
        <td>
          <span class="bolt-1">
            &#x26A1;&#xFE0E;
          </span>
        </td>
        <td>
          
            <span class="bolt-1">
              &#x26A1;&#xFE0E;
            </span>
          
        </td>
      </tr>
    
  </tbody>
</table>
</div>

<h2 id="expectedactual-output">Expected/Actual Output</h2>
<details class="note-card">
  <summary>Note</summary>
  <div class="note-card-body">
    <p>Our setup was not robust enough to handle testing at the full 65W or 100W that certain chargers are rated for. That is why we tested each charger at <em>one</em> of its max current/voltage configurations. Say Charger A is called a "65W" charger on the box. Charger A supports:</p>
    <ul>
      <li>20V, up to 3.25 A (to reach max power of 65W)</li>
    </ul>
    <p>And it <em>also</em> supports:</p>
    <ul>
      <li>5V, up to 3 A</li>
      <li>9V, up to 3 A</li>
      <li>12V, up to 3 A</li>
      <li>15V, up to 3 A</li>
    </ul>
    <p>In this case, we'd do base level testing to see if we can get the charger to output its max power for a second or two. Then, for the oscilloscope traces, we'd drop the device down to something like 9V and cycle through all its current levels. This avoids overheating our breakout board. As stated earlier, <em>all</em> chargers showed similar noise profiles at their different voltages, so we're confident that the results you see below are reliable.</p>
  </div>
</details>

<p>The Actual Voltage column is highlighted <span class="diff-pos">green</span> if the measured voltage is within ±5% of the nominal output voltage (the USB-C PD spec limit) and <span class="diff-neg">red</span> if it falls outside that window in either direction. For example, a 5V output must stay between 4.75V and 5.25V.</p>

<h3 id="expectedactual-output-table">Expected/Actual Output Table</h3>

<p>The DC items in here, like the Macbook Pro, are colored in grey to avoid conflating them with the AC chargers. They’re just included here for reference.</p>

<div class="table-wrapper">
<table class="stats-table">
  <thead>
    <tr>
      <th>Charger</th>
      <th>Attempted To Pull (W)</th>
      <th>Actual Voltage (V)</th>
      <th>Actual Current (A)</th>
      <th>Actual Power (W)</th>
      <th>Passes Spec?</th>
    </tr>
  </thead>
  <tbody>
    <tr><td><strong>Eero 15W Charger</strong></td><td>15 (5v, 3a)</td><td class="diff-pos">4.76</td><td>2.91</td><td>13.85</td><td class="diff-pos">&#x2713;</td></tr>
    <tr><td><strong>Shargeek Macintosh Charger</strong></td><td>27 (9v, 3a)</td><td class="diff-pos">8.9</td><td>3.0</td><td>27.0</td><td class="diff-pos">&#x2713;</td></tr>
    <tr><td><strong>Apple 30W Retail Charger</strong></td><td>30 (20v, 1.5a)</td><td class="diff-pos">20.04</td><td>1.42</td><td>28.45</td><td class="diff-pos">&#x2713;</td></tr>
    <tr><td><strong>Apple HomePod Mini Charger</strong></td><td>19.98 (9v 2.22a)</td><td class="diff-pos">8.90</td><td>2.23</td><td>19.85</td><td class="diff-pos">&#x2713;</td></tr>
    <tr><td><strong>Vebner GaN 65W Charger</strong></td><td>27 (9v, 3a)</td><td class="diff-pos">8.64</td><td>3.04</td><td>26.26</td><td class="diff-pos">&#x2713;</td></tr>
    <tr><td><strong>Govee Power Supply</strong><span class="usba-badge">USB A Only</span></td><td>10 (5v, 2a)</td><td class="diff-pos">5.04</td><td>2.02</td><td>10.18</td><td class="diff-pos">&#x2713;</td></tr>
    <tr><td><strong>Counterfeit AT&amp;T</strong><span class="usba-badge">USB A Only</span></td><td>10 (5v, 2a)</td><td class="diff-neg">5.38</td><td>2.01</td><td>10.81</td><td class="diff-neg">&#x2717;</td></tr>
    <tr><td><strong>Counterfeit Samsung</strong></td><td>10 (5v, 2a)</td><td class="diff-neg">4.4</td><td>2.0</td><td>8.9</td><td class="diff-neg">&#x2717;</td></tr>
    <tr><td><strong>Amazon Kindle Charger</strong></td><td>9.36 (5.2v, 1.8a)</td><td class="diff-neg">5.30</td><td>1.81</td><td>9.59</td><td class="diff-neg">&#x2717;</td></tr>
    <tr><td><strong>Counterfeit Chinese Wall Charger</strong><span class="usba-badge">USB A Only</span></td><td>10.5 (5v, 2.1a)</td><td class="diff-neg">4.5</td><td>2.13</td><td>9.6</td><td class="diff-neg">&#x2717;</td></tr>
    <tr><td><strong>Dealworthy Charger</strong></td><td>20 (12v, 1.67a)</td><td class="diff-pos">11.97</td><td>1.57</td><td>18.79</td><td class="diff-pos">&#x2713;</td></tr>
    <tr class="battery-row"><td><strong>Anker 621 MAG GO 5000mAh Battery</strong></td><td>12</td><td class="diff-neg">4.74</td><td>2.43</td><td>11.54</td><td class="diff-neg">&#x2717;</td></tr>
    <tr class="battery-row"><td><strong>iPhone 17 pro</strong></td><td>4.5</td><td class="diff-pos">4.81</td><td>1.12</td><td>5.39</td><td class="diff-pos">&#x2713;</td></tr>
    <tr class="battery-row"><td><strong>Macbook Pro M1</strong></td><td>15 (5v, 3a)</td><td class="diff-pos">5.05</td><td>3.03</td><td>15.30</td><td class="diff-pos">&#x2713;</td></tr>
    <tr><td><strong>Anker ASPD053a</strong></td><td>27 (9v, 3a)</td><td class="diff-pos">8.88</td><td>3.02</td><td>26.82</td><td class="diff-pos">&#x2713;</td></tr>
    <tr><td><strong>Apple 96W Macbook Charger</strong></td><td>45 (15v, 3a)</td><td class="diff-pos">15.08</td><td>3.02</td><td>45.54</td><td class="diff-pos">&#x2713;</td></tr>
    <tr><td><strong>AOHI 100W GaN Charger</strong></td><td>36 (12v, 3a)</td><td class="diff-pos">11.82</td><td>3.02</td><td>35.52</td><td class="diff-pos">&#x2713;</td></tr>
    <tr><td><strong>Anker 637 Magnetic Charging Station 1 - USB A port</strong><span class="usba-badge">USB A</span></td><td>12 (5v, 2.4a)</td><td class="diff-pos">5.13</td><td>2.42</td><td>12.41</td><td class="diff-pos">&#x2713;</td></tr>
    <tr><td><strong>Anker 637 Magnetic Charging Station 2 - USB C port</strong></td><td>36 (12v, 3a)</td><td class="diff-pos">11.79</td><td>3.02</td><td>35.65</td><td class="diff-pos">&#x2713;</td></tr>
    <tr><td><strong>Spigen PowerArc ArcStation Pro</strong></td><td>27 (9v, 3a)</td><td class="diff-pos">8.91</td><td>3.02</td><td>26.91</td><td class="diff-pos">&#x2713;</td></tr>
    <tr><td><strong>Anker A121D 45W iPhone 17 Charger</strong></td><td>45 (15v, 3a)</td><td class="diff-pos">14.82</td><td>3.03</td><td>44.90</td><td class="diff-pos">&#x2713;</td></tr>
    <tr><td><strong>Anker A121B 100W Charger</strong></td><td>45 (15v, 3a)</td><td class="diff-pos">14.99</td><td>3.02</td><td>45.26</td><td class="diff-pos">&#x2713;</td></tr>
    <tr><td><strong>AOHI GaN 65W Charger</strong></td><td>36 (12v, 3a)</td><td class="diff-pos">12.13</td><td>3.02</td><td>36.63</td><td class="diff-pos">&#x2713;</td></tr>
  </tbody>
</table>
</div>

<style>
  table {
    border-collapse: collapse;
    width: 100%;
    min-width: 600px; /* Force scroll on mobile */
    font-family: sans-serif;
    font-size: calc(1em - 1px);
  }
  th, td {
    border: 1px solid var(--table-cell-border);
    text-align: left;
    padding: 6px 8px;
  }
  th {
    background-color: var(--table-head-bg);
  }
  /* Bolt colors: evenly-spaced red→orange→amber→lime→green gradient */
  .bolt-5 { color: #15933f; font-weight: 900; -webkit-text-stroke: 1px #15933f; }
  .bolt-4 { color: #7ad025; font-weight: 900; -webkit-text-stroke: 1px #7ad025; }
  .bolt-3 { color: #f2c336; font-weight: 900; -webkit-text-stroke: 1px #f2c336; }
  .bolt-2 { color: #f08b42; font-weight: 900; -webkit-text-stroke: 1px #f08b42; }
  .bolt-1 { color: #e02929; font-weight: 900; -webkit-text-stroke: 1px #e02929; }
  @media (prefers-color-scheme: dark) {
    /* Bright gradient for dark table backgrounds */
    table .bolt-5 { color: #42d773; -webkit-text-stroke: 1px #42d773; }
    table .bolt-4 { color: #8cd742; -webkit-text-stroke: 1px #8cd742; }
    table .bolt-3 { color: #eebd2b; -webkit-text-stroke: 1px #eebd2b; }
    table .bolt-2 { color: #f08b42; -webkit-text-stroke: 1px #f08b42; }
    table .bolt-1 { color: #e96363; -webkit-text-stroke: 1px #e96363; }
  }
  html[data-theme="dark"] table .bolt-5 { color: #42d773; -webkit-text-stroke: 1px #42d773; }
  html[data-theme="dark"] table .bolt-4 { color: #8cd742; -webkit-text-stroke: 1px #8cd742; }
  html[data-theme="dark"] table .bolt-3 { color: #eebd2b; -webkit-text-stroke: 1px #eebd2b; }
  html[data-theme="dark"] table .bolt-2 { color: #f08b42; -webkit-text-stroke: 1px #f08b42; }
  html[data-theme="dark"] table .bolt-1 { color: #e96363; -webkit-text-stroke: 1px #e96363; }
  html[data-theme="light"] table .bolt-5 { color: #15933f; -webkit-text-stroke: 1px #15933f; }
  html[data-theme="light"] table .bolt-4 { color: #7ad025; -webkit-text-stroke: 1px #7ad025; }
  html[data-theme="light"] table .bolt-3 { color: #f2c336; -webkit-text-stroke: 1px #f2c336; }
  html[data-theme="light"] table .bolt-2 { color: #f08b42; -webkit-text-stroke: 1px #f08b42; }
  html[data-theme="light"] table .bolt-1 { color: #e02929; -webkit-text-stroke: 1px #e02929; }
</style>

<p><br /></p>

<style>
  body { overflow-x: hidden; }
  .device-scroller {
    width: 100vw;
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
    position: relative;
    display: flex;
    align-items: flex-start;
    overflow-x: scroll;
    gap: 30px;
    padding: 24px 10%;
    padding-bottom: 10px;
    -webkit-overflow-scrolling: touch;
    height: 645px;
    box-sizing: border-box;
    scroll-behavior: smooth;
    -ms-overflow-style: none;
    scrollbar-width: none;
  }
  .device-scroller::-webkit-scrollbar {
    display: none;
  }

  /* Custom scrollbar - always visible */
  .custom-scroll-area {
    width: 100vw;
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
    padding: 0 10%;
    box-sizing: border-box;
    position: relative;
    height: 30px;
    display: flex;
    align-items: center;
    margin-top: -6px;
  }
  .custom-scroll-track {
    width: 100%;
    height: 8px;
    background: rgba(150, 150, 150, 0.35);
    border-radius: 4px;
    position: relative;
    cursor: pointer;
  }
  .custom-scroll-thumb {
    position: absolute;
    height: 22px;
    top: 50%;
    transform: translateY(-50%);
    background: #999;
    border-radius: 11px;
    cursor: grab;
    min-width: 60px;
    transition: background 0.15s ease;
  }
  .custom-scroll-thumb:hover {
    background: #777;
  }
  .custom-scroll-thumb:active {
    background: #666;
    cursor: grabbing;
  }
  .quality-labels-bar {
    width: 100vw;
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
    display: flex;
    justify-content: space-between;
    padding: 2px 10%;
    box-sizing: border-box;
    opacity: 0.7;
    font-family: sans-serif;
    font-size: 0.78em;
    font-weight: 700;
    letter-spacing: 3px;
    text-transform: uppercase;
    color: var(--muted-fg);
    user-select: none;
    pointer-events: none;
    margin-top: 2px;
  }
  .card-column {
    flex: 0 0 820px;
    display: flex;
    flex-direction: column;
    gap: 6px;
  }
  .card-title-above {
    font-family: sans-serif;
    font-size: 1.05em;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 2.5px;
    color: rgba(0, 0, 0, 0.65);
    padding-left: 4px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    user-select: none;
  }
  @media (prefers-color-scheme: dark) {
    .card-title-above {
      color: rgba(255, 255, 255, 0.55);
    }
  }
  html[data-theme="dark"] .card-title-above { color: rgba(255, 255, 255, 0.55); }
  html[data-theme="light"] .card-title-above { color: rgba(0, 0, 0, 0.65); }
  .device-card {
    height: 565px;
    margin: 0;
    position: relative;
    display: flex;
    flex-direction: row;
    border-radius: 20px;
    padding: 0;
    border: 1px solid rgba(0,0,0,0.08);
    box-sizing: border-box;
    overflow: hidden;
    transition: transform 0.2s ease;
  }
  .device-content {
    flex: 1;
    display: flex;
    flex-direction: row;
    padding: 24px;
    gap: 24px;
    min-height: 0;
    overflow: hidden;
    cursor: pointer;
  }
  .device-images {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 12px;
    flex: 0 0 400px;
  }
  .device-images img {
    width: 100%;
    height: auto;
    max-height: 290px;
    object-fit: cover;
    border-radius: 10px;
    border: 1px solid #ddd;
    background: #fff;
  }
  .device-info {
    flex: 1;
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    min-height: 0;
    overflow: hidden;
  }
  .device-rating {
    font-size: 0.85em;
    font-family: sans-serif;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 15px;
    align-self: flex-end;
    padding: 6px 12px;
    border-radius: 8px;
    border-width: 1px;
    border-style: solid;
    font-weight: 700;
  }
  .rating-badge-5 { background: rgba(46, 204, 113, 0.22); border-color: rgba(46, 204, 113, 0.55); color: #145a30; }
  .rating-badge-4 { background: rgba(74, 222, 128, 0.22); border-color: rgba(74, 222, 128, 0.55); color: #166534; }
  .rating-badge-3 { background: rgba(134, 239, 172, 0.22); border-color: rgba(134, 239, 172, 0.55); color: #14532d; }
  .rating-badge-2 { background: rgba(250, 204, 21, 0.22); border-color: rgba(250, 204, 21, 0.55); color: #854d0e; }
  .rating-badge-1 { background: rgba(248, 113, 113, 0.22); border-color: rgba(248, 113, 113, 0.55); color: #991b1b; }

  @media (prefers-color-scheme: dark) {
    /* Card bg is light pastel in both modes, so dark text colors stay the same */
    .rating-badge-5 { background: rgba(46, 204, 113, 0.22); border-color: rgba(46, 204, 113, 0.55); color: #145a30; }
    .rating-badge-4 { background: rgba(74, 222, 128, 0.22); border-color: rgba(74, 222, 128, 0.55); color: #166534; }
    .rating-badge-3 { background: rgba(134, 239, 172, 0.22); border-color: rgba(134, 239, 172, 0.55); color: #14532d; }
    .rating-badge-2 { background: rgba(250, 204, 21, 0.22); border-color: rgba(250, 204, 21, 0.55); color: #854d0e; }
    .rating-badge-1 { background: rgba(248, 113, 113, 0.22); border-color: rgba(248, 113, 113, 0.55); color: #991b1b; }
  }
  /* These badges sit on pastel card backgrounds so colors are the same in both themes */
  html[data-theme="dark"] .rating-badge-5 { background: rgba(46, 204, 113, 0.22); border-color: rgba(46, 204, 113, 0.55); color: #145a30; }
  html[data-theme="dark"] .rating-badge-4 { background: rgba(74, 222, 128, 0.22); border-color: rgba(74, 222, 128, 0.55); color: #166534; }
  html[data-theme="dark"] .rating-badge-3 { background: rgba(134, 239, 172, 0.22); border-color: rgba(134, 239, 172, 0.55); color: #14532d; }
  html[data-theme="dark"] .rating-badge-2 { background: rgba(250, 204, 21, 0.22); border-color: rgba(250, 204, 21, 0.55); color: #854d0e; }
  html[data-theme="dark"] .rating-badge-1 { background: rgba(248, 113, 113, 0.22); border-color: rgba(248, 113, 113, 0.55); color: #991b1b; }
  .device-card figcaption {
    font-size: 0.85em;
    font-family: sans-serif;
    line-height: 1.6;
    color: #444;
    overflow-y: auto;
    word-wrap: break-word;
    flex: 1;
    white-space: pre-wrap;
    padding-right: 12px;
  }
  .device-card figcaption::-webkit-scrollbar {
    width: 8px;
  }
  .device-card figcaption::-webkit-scrollbar-track {
    background: rgba(0,0,0,0.03);
    border-radius: 4px;
  }
  .device-card figcaption::-webkit-scrollbar-thumb {
    background: rgba(0,0,0,0.1);
    border-radius: 4px;
  }
  .device-card figcaption::-webkit-scrollbar-thumb:hover {
    background: rgba(0,0,0,0.15);
  }
  .expand-btn {
    align-self: flex-end;
    margin-top: auto;
    background: rgba(0, 0, 0, 0.04);
    color: #555;
    border: 1px solid rgba(0, 0, 0, 0.12);
    padding: 10px 44px;
    border-radius: 6px;
    cursor: pointer;
    font-size: 0.9em;
    font-weight: 700;
    font-family: sans-serif;
    text-transform: uppercase;
    letter-spacing: 1.8px;
    transition: color 0.25s ease, background 0.25s ease, border-color 0.25s ease;
    display: inline-flex;
    align-items: center;
    gap: 6px;
  }
  .expand-btn::after {
    content: '→';
    display: inline-block;
    font-size: 1.1em;
    transition: color 0.25s ease;
  }
  .expand-btn:hover {
    background: rgba(0, 0, 0, 0.08);
    color: #222;
    border-color: rgba(0, 0, 0, 0.25);
  }

  /* Modal Styles */
  #device-modal {
    display: none;
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0,0,0,0);
    backdrop-filter: blur(0px);
    z-index: 10000;
    align-items: center;
    justify-content: center;
    flex-direction: column;
    padding: 40px;
    box-sizing: border-box;
    transition: background 0.35s ease, backdrop-filter 0.35s ease;
  }
  #device-modal.modal-open {
    background: rgba(0,0,0,0.82);
    backdrop-filter: blur(6px);
  }
  #device-modal.modal-open.modal-danger {
    background: rgba(90,0,0,0.88);
    backdrop-filter: blur(6px);
  }
  .modal-dismiss-hint {
    position: absolute;
    font-family: sans-serif;
    color: rgba(255,255,255,0.55);
    font-size: 0.82em;
    letter-spacing: 1.5px;
    user-select: none;
    pointer-events: none;
  }
  .modal-dismiss-hint.bottom { bottom: 18px; left: 50%; transform: translateX(-50%); }
  .modal-wrapper {
    position: relative;
    width: 90%;
    max-width: 1100px;
    height: calc(100vh - 120px);
    display: flex;
    flex-direction: column;
  }
  .modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 12px;
    flex-shrink: 0;
  }
  .modal-title {
    font-family: sans-serif;
    font-size: 1.5em;
    font-weight: 700;
    color: rgba(255,255,255,0.88);
    letter-spacing: 1px;
    padding-left: 4px;
    transition: opacity 0.3s ease;
  }
  .modal-close-btn {
    background: none;
    border: none;
    color: rgba(180, 60, 60, 0.7);
    font-size: calc(1.6em + 1px);
    font-weight: 900;
    -webkit-text-stroke: 1.5px currentColor;
    cursor: pointer;
    padding: 4px 10px;
    line-height: 1;
    font-family: sans-serif;
    transition: color 0.2s ease;
    user-select: none;
  }
  .modal-close-btn:hover {
    color: rgba(220, 60, 60, 1);
  }
  .modal-container {
    background: #111;
    width: 100%;
    flex: 1;
    min-height: 0;
    border-radius: 12px;
    position: relative;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    transform: scale(0.3);
    opacity: 0;
    transition: transform 0.45s cubic-bezier(0.76, 0, 0.24, 1), opacity 0.35s cubic-bezier(0.76, 0, 0.24, 1);
    transform-origin: center center;
  }
  #device-modal.modal-open .modal-container {
    transform: scale(1);
    opacity: 1;
  }
  .modal-body {
    padding: 0;
    overflow: hidden;
    flex: 1;
    min-height: 0;
    display: grid;
    grid-template-columns: 3fr 2fr;
    background: #111;
  }
  .modal-body .modal-imgs {
    display: flex;
    flex-direction: column;
    gap: 0;
    min-height: 0;
    background: #111;
    overflow: hidden;
  }
  .modal-body img {
    flex: 1;
    min-height: 0;
    width: 100%;
    object-fit: contain;
    cursor: zoom-in;
  }
  .modal-body p::-webkit-scrollbar {
    width: 10px;
  }
  .modal-body p::-webkit-scrollbar-track {
    background: #111;
  }
  .modal-body p::-webkit-scrollbar-thumb {
    background: #333;
    border-radius: 10px;
  }
  .modal-body p::-webkit-scrollbar-thumb:hover {
    background: #444;
  }
  .modal-text-panel {
    display: flex;
    flex-direction: column;
    align-items: center;
    background: #111;
    overflow-y: auto;
    min-height: 0;
    padding: 0 10px 0 15px;
  }
  .modal-text-panel::-webkit-scrollbar {
    width: 10px;
  }
  .modal-text-panel::-webkit-scrollbar-track {
    background: #111;
  }
  .modal-text-panel::-webkit-scrollbar-thumb {
    background: #333;
    border-radius: 10px;
  }
  .modal-text-panel::-webkit-scrollbar-thumb:hover {
    background: #444;
  }
  .modal-ratings-summary {
    padding: 30px 0 10px 0;
    max-width: 354px;
    width: 100%;
    box-sizing: border-box;
    border-bottom: 1px solid rgba(255,255,255,0.05);
    display: flex;
    flex-direction: column;
    gap: 8px;
  }
  .modal-ratings-summary .rating-item {
    font-family: sans-serif;
    color: #eee;
    font-size: 0.95em;
    display: flex;
    align-items: center;
    gap: 12px;
  }
  .modal-ratings-summary .label {
    font-weight: 700;
    color: #888;
    text-transform: uppercase;
    font-size: 0.85em;
    letter-spacing: 1px;
    width: 110px;
  }
  .modal-body p {
    font-size: 0.95em;
    font-family: sans-serif;
    line-height: 1.6;
    color: #888;
    margin: 0;
    padding: 20px 0 40px 0;
    max-width: 354px;
    width: 100%;
    box-sizing: border-box;
    white-space: pre-wrap;
    background: transparent;
    overflow-y: visible; /* Scroll is handled by modal-text-panel now */
  }
  .modal-close-bottom {
    display: none;
    align-items: center;
    justify-content: center;
    width: 100%;
    padding: 18px;
    margin: 0;
    background: rgba(255, 255, 255, 0.06);
    color: rgba(255, 255, 255, 0.7);
    border: none;
    border-top: 1px solid rgba(255, 255, 255, 0.08);
    font-family: sans-serif;
    font-size: 0.9em;
    font-weight: 800;
    letter-spacing: 3px;
    text-transform: uppercase;
    cursor: pointer;
    flex-shrink: 0;
  }

  /* MOBILE OPTIMIZATIONS (Smart Media Queries) */
  @media (max-width: 768px) {
    .device-scroller {
      padding: 24px 15px 10px 15px;
      height: 666px;
      align-items: stretch;
    }
    .card-column {
      flex: 0 0 calc(100vw - 30px);
      flex-shrink: 0;
      height: 100%;
    }
    .card-title-above {
      padding: 4px 12px;
      text-align: center;
      font-size: 0.75em;
      white-space: normal;
      line-height: 1.3;
      color: rgba(180, 180, 180, 0.85);
      border: 1.5px solid rgba(180, 180, 180, 0.4);
      border-radius: 8px;
      align-self: center;
    }
    .device-card {
      flex-direction: column;
      height: auto;
      flex: 1;
      padding-left: 0;
    }
    .device-content {
      flex-direction: column;
      padding: 16px;
      gap: 12px;
      flex: 1;
      min-height: 0;
      overflow: hidden;
    }
    .device-images {
      width: 100%;
      flex: 0 0 200px;
      overflow: hidden;
    }
    .device-images img {
      flex: 1;
      min-height: 0;
      height: 0;
      max-height: none;
      object-fit: cover;
      background: #111;
      border-color: transparent;
    }
    .device-info {
      padding-top: 0;
      flex: 1;
      min-height: 0;
      overflow-y: auto;
    }
    .device-rating {
      align-self: flex-start;
      justify-content: flex-start;
      font-size: 0.9em;
    }
    .expand-btn {
      align-self: stretch;
      justify-content: center;
      padding: 10px 20px;
    }

    /* Modal Mobile - Full-screen scrollable layout */
    #device-modal {
      padding: 0;
    }
    .modal-wrapper {
      width: 100%;
      height: 100%;
      max-width: none;
    }
    .modal-header {
      position: fixed;
      top: 0;
      left: 0;
      right: 0;
      z-index: 10;
      background: linear-gradient(to bottom, rgba(0,0,0,0.9) 0%, rgba(0,0,0,0.6) 70%, transparent 100%);
      padding: 12px 16px;
      margin-bottom: 0;
    }
    .modal-title {
      font-size: 1.1em;
    }
    .modal-container {
      border-radius: 0;
      height: 100%;
    }
    .modal-body {
      display: flex;
      flex-direction: column;
      overflow-y: auto;
      -webkit-overflow-scrolling: touch;
    }
    .modal-body .modal-imgs {
      flex: none;
      height: auto;
      border-bottom: none;
      padding-top: 60px;
    }
    .modal-body .modal-imgs a {
      display: block !important;
      flex: none !important;
    }
    .modal-body img {
      flex: none;
      width: 100%;
      height: auto;
      max-height: 45vh;
      object-fit: contain;
      background: #000;
    }
    .modal-text-panel {
      flex: none;
      overflow-y: visible;
      padding: 0 20px;
      align-items: flex-start;
    }
    .modal-ratings-summary {
      padding: 20px 0 10px 0;
      max-width: none;
    }
    .modal-body p {
      padding: 12px 0 20px 0;
      max-width: none;
      font-size: 0.9em;
    }
    .modal-close-bottom {
      display: flex;
    }
    .modal-dismiss-hint {
      display: none;
    }
    .custom-scroll-area {
      padding: 0 15px;
      margin-top: -2px;
    }
    .quality-labels-bar {
      padding: 4px 15px;
      font-size: 0.72em;
      letter-spacing: 2px;
    }
  }
</style>

<h2 id="overcurrent-testing">Overcurrent Testing</h2>

<p>The last piece of Ken Shirriff’s testing we wanted to replicate was overcurrent. Naturally, since devices get to decide how much current they want to pull, it’s up to the charger to make sure the device doesn’t pull too much current. Chargers generally have two strategies to deal with this: 
1) shut off completely, or 
2) reduce the output voltage. 
Option 1 is preferred in most cases. Option 2 is really just a consequence of not doing option 1. There is a third scenario, where the charger can somehow increase the current at the same voltage, but this would probably mean overheating it.</p>

<details class="note-card">
  <summary>Note</summary>
  <div class="note-card-body">
    <p>During overcurrent testing, we set the electronic load to keep pulling more and more current until the charger shut off. While Ken was able to display the relationship between voltage and overcurrent on beautiful time-based graphs, we lack that recording capability. So our results are very simple.</p>
    <p>In case you're interested, all my voltage graphs were relatively tight during overcurrent testing, and we only had one charger (Counterfeit Samsung) that completely blew the test. The others did a great job of keeping their voltage within a reasonable range, even during overcurrent. For that reason, we would say the values below are the true values of the voltage and current of the device at their shutoff period.</p>
  </div>
</details>

<figure style="max-width: 600px; text-align: center;">
  <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/load_example.png" alt="Ken current" style="width: 100%;" />
  <figcaption>A good example of Ken's overcurrent graphs. I wasn't able to recreate his setup like this.</figcaption>
</figure>
<figure style="max-width: 600px; text-align: center;">
  <img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/ken_bad.png" alt="Ken current 2" style="width: 100%;" />
  <figcaption>An example of a bad charger Ken tested. While I wasn't able to capture graphs like this and save them, what I can say is that my graphs all looked like the earlier one, not this one (with the exception of counterfeit samsung)</figcaption>
</figure>

<p>The ideal value here is having a voltage equal to 5V or 9V. You don’t want 3 or 4 volts, or 7 or 8 volts, because that suggests the charger allowed more current out than it should have.</p>

<p><em>We don’t have overcurrent results for all chargers in the table below. This will be updated as more test results become available.</em></p>

<h3 id="overcurrent-results-table">Overcurrent Results Table</h3>
<style>
  .overcurrent-table {
    border-collapse: collapse;
    width: 100%;
    min-width: 600px;
    font-family: sans-serif;
    font-size: calc(1em - 1px);
  }
  .overcurrent-table th, .overcurrent-table td {
    border: 1px solid var(--table-cell-border);
    text-align: left;
    padding: 6px 10px;
  }
  .overcurrent-table th {
    background-color: var(--table-head-bg);
  }
  .overcurrent-table td:nth-child(1) {
    background-color: rgba(0, 0, 0, 0.03);
  }
  @media (prefers-color-scheme: dark) {
    .overcurrent-table td:nth-child(1) {
      background-color: rgba(255, 255, 255, 0.04);
    }
  }
  html[data-theme="dark"] .overcurrent-table td:nth-child(1) { background-color: rgba(255, 255, 255, 0.04); }
  html[data-theme="light"] .overcurrent-table td:nth-child(1) { background-color: rgba(0, 0, 0, 0.03); }
</style>

<div class="table-wrapper">
<table class="overcurrent-table">
  <thead>
    <tr>
      <th>Adapter</th>
      <th>Difference between advertised Current and Current at shutoff</th>
      <th>Difference between advertised Voltage and Voltage at shutoff</th>
      <th>Difference between advertised Power and Power at Shutoff (W)</th>
    </tr>
  </thead>
  <tbody>
    <tr><td><strong>Vebner GaN</strong></td><td class="diff-pos">0.42</td><td class="diff-pos">0.13</td><td class="diff-pos">2.5</td></tr>
    <tr><td><strong>AOHI GaN 100W</strong></td><td class="diff-pos">0.6</td><td class="diff-pos">0.13</td><td class="diff-pos">3.5</td></tr>
    <tr><td><strong>Anker A121B 100W GaN Charger</strong></td><td class="diff-pos">0.35</td><td class="diff-pos">0.12</td><td class="diff-pos">2.2</td></tr>
    <tr><td><strong>Anker A121D 45W iPhone 17 Charger</strong></td><td class="diff-pos">0.44</td><td class="diff-neg">-0.09</td><td class="diff-pos">1.9</td></tr>
    <tr><td><strong>Anker 637 Magnetic Charging Station 2 - USB C port</strong></td><td class="diff-pos">0.7</td><td class="diff-neg">-0.22</td><td class="diff-pos">7.6</td></tr>
    <tr><td><strong>Apple HomePod Mini (20W)</strong></td><td class="diff-pos">0.42</td><td class="diff-neg">-0.11</td><td class="diff-pos">1.7</td></tr>
    <tr><td><strong>Apple 30W Retail</strong></td><td class="diff-pos">0.17</td><td class="diff-neg">-0.14</td><td class="diff-pos">0.4</td></tr>
    <tr><td><strong>Apple 96W</strong></td><td class="diff-pos">0.46</td><td class="diff-neg">-0.37</td><td class="diff-pos">1.1</td></tr>
    <tr><td><strong>Amazon Kindle</strong></td><td class="diff-pos">0.1</td><td class="diff-neg">-0.4</td><td class="diff-neg">-0.2</td></tr>
    <tr><td><strong>Spigen PowerArc ArcStation</strong></td><td class="diff-pos">0.22</td><td class="diff-neg">-0.27</td><td class="diff-pos">0.2</td></tr>
    <tr><td><strong>AOHI GaN 65W Charger</strong></td><td class="diff-pos">0.33</td><td class="diff-neg">-0.3</td><td class="diff-pos">0.7</td></tr>
    <tr><td><strong>Eero 15W Charger</strong></td><td class="diff-pos">0.36</td><td class="diff-neg">-0.31</td><td class="diff-pos">0.8</td></tr>
    <tr><td><strong>Counterfeit Chinese Wall Charger</strong></td><td class="diff-pos">0.23</td><td class="diff-neg">-0.57</td><td class="diff-neg">-0.2</td></tr>
    <tr><td><strong>Counterfeit Samsung</strong></td><td class="diff-pos">0.81</td><td class="diff-neg">-1.2</td><td class="diff-pos">0.64</td></tr>
  </tbody>
</table>
</div>

<p>A mixed bag of results from overcurrent. The Kindle is the most disappointing one in my opinion, because it shut off so quickly at just 0.1 A above its rated current, and somehow its voltage still dropped. However, the worst offenders are from the Apple 96W, Spigen PowerArc, Eero, and the counterfeit Chinese wall charger. All had voltage drops that suggest they go below what would be considered USB standards.</p>

<p><em>A new update: I re-ran the tests one more time with a brand new multimeter and updated the table. Upon reviewing, the <strong>Spigen, Apple 96W, Counterfeit Chinese wall charger, AOHI GaN 65W, and Amazon Kindle, and Eero</strong> are all starting to break past the +/- 5% voltage threshold for USB certification.</em>
<em>I re-tested them under the oscilloscope, and found some interesting results: while most of these chargers offered relatively focused voltage traces, usually ranging by about 0.1V, the counterfeit Samsung was the one outlier. This charger had such a noisy voltage trace that, near shutoff, it oscillated between 3.7 V, 0, and 8.5 V. This dangerous behavior was truly unique and not present in *any</em> of the other chargers I tested. When your phone or laptop attempts to pull too much current, this charger will start sending massive shockwaves of voltage.*</p>

<p><br />
<br />
—
<br /></p>

<h2 id="conclusion">Conclusion</h2>

<p>Wow, that was a lot. Evaluating chargers seemed quite difficult at first, but this whole project quickly turned into something exciting. What I liked most about this is that you don’t need to be an electrical engineer to see the difference between good and bad chargers. The oscilloscope really does make it obvious. Things get confusing when you go past the ‘what’ and try to start understanding the <em>why</em>. <em>Why</em> certain peaks appear in the FFT, <em>why</em> some scope traces look as bad as they do, or <em>why</em> a charger measured fine at 1A but looked terrible at 2.5A. I don’t think Spencer or myself have great answers to these.</p>

<p>The practical takeaway, in my opinion, is that most name-brand chargers of today are unlikely to damage your phone battery. Since modern devices filter noise internally, and the majority of these chargers stayed within that USB spec of ±5% voltage tolerance, they’re unlikely to be a problem. Just avoid excessively cheap, no-name chargers and you should be fine.</p>

<p>I hope you enjoyed reading. This really was a pleasure to put together. Car chargers are next on my list, and I suspect that may be a story of its own. If you have any suggestions to make, corrections to add, or just want to share something you found interesting, feel free to reach out and let me know. Contact is on the About page.</p>

<h3 id="-sean">-Sean</h3>
<p><br />
Last thing: a huge shout out to both Ken and Spencer! I could not have done this without either of them.</p>
<figure style="max-width: 600px; text-align: center;">
  <a href="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/spencerandsean1.jpg"><img src="/assets/images/2026-01-19-a-dozen-chargers-in-the-lab/spencerandsean1.jpg" alt="Spencer and Sean" style="width: 100%;" /></a>
  <figcaption>Me and Spencer. Best friends make good electrical testing partners!</figcaption>
</figure>

<p><br />
Sean Sullivan<br />
A Dozen Chargers in the lab</p>

<h3 id="appendix">Appendix</h3>

<p>[A1] <em>Tip: If you want to do testing of your own, always use the spring ground clip. Using the default alligator ground clip will lead to extremely high noise ratings.</em></p>]]></content><author><name>Sean Sullivan</name></author><category term="technology" /><summary type="html"><![CDATA[A Dozen+ Chargers in the Lab: Apple is Okay, but Not the Best]]></summary></entry><entry><title type="html">Welcome to My Blog</title><link href="https://sull1van.com/welcome-to-my-blog.html" rel="alternate" type="text/html" title="Welcome to My Blog" /><published>2026-01-18T00:00:00+00:00</published><updated>2026-01-18T00:00:00+00:00</updated><id>https://sull1van.com/welcome-to-my-blog</id><content type="html" xml:base="https://sull1van.com/welcome-to-my-blog.html"><![CDATA[<h2 id="introduction">Introduction</h2>

<p>For years, I had this website as an email domain, using it with iCloud so I could email people from @sull1van.com. I realized that I made a lot of personal content which should be published somewhere, so I turned this into a real site. I’m an industrial engineer currently living in the United States, with passions for engineering and health. Most of the things I publish will be related to those two things.</p>

<h2 id="other-info">Other info</h2>

<p>This blog is built with Jekyll and focuses on content over presentation. I tried using blogging services but they were all pretty bad, so I vibe coded my own.</p>

<p>Stay tuned for more posts!</p>]]></content><author><name>Sean Sullivan</name></author><category term="meta" /><category term="blogging" /><summary type="html"><![CDATA[Introduction]]></summary></entry></feed>