<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xml:base="https://JackHPeterson.com" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Jack H. Peterson</title>
    <link>https://JackHPeterson.com</link>
    <atom:link href="https://jackhpeterson.com/rss.xml" rel="self" type="application/rss+xml" />
    <description></description>
    <language></language>
    <item>
      <title></title>
      <link>https://jackhpeterson.com/posts/0020/</link>
      <description>&lt;h1&gt;Enhancing Elm: Understanding Getters, Proxies, and Performance Measurement&lt;/h1&gt;
&lt;p&gt;Measuring performance in Elm is a unique challenge due to Elm&#39;s functional nature, but I&#39;ve got an interesting, hacky, solution. By mixing flags, decoders, getters, and proxies accurate performance measurement is possible in Elm. Let&#39;s take a closer look!&lt;/p&gt;
&lt;h2&gt;The Challenge of Measuring Performance in Elm&lt;/h2&gt;
&lt;p&gt;Elm&#39;s functional architecture brings its own set of challenges when it comes to traditional performance measurement. Elm is a purely functional language, so it doesn&#39;t have a way to get the time synchronously. This is because getting the time is an inherently impure call. If get the time, and then get the time a second later, it&#39;s not the same result. That&#39;s textbook functional impurity.&lt;/p&gt;
&lt;p&gt;Generally speaking, the elm community will point you to flame charts and other tools to measure performance. However, these tools don&#39;t always provide the level of granularity needed to identify performance bottlenecks, and for newbies, they can be brutally difficult to understand. The greater Javascript Ecosystem can use APIs like &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Performance&quot;&gt;Performance&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;The JS Performance API&lt;/h2&gt;
&lt;p&gt;The performance API is a handy tool for measuring performance in JavaScript. It provides a way to create marks and measures, which can be used to measure the time between two points in code. It also provides a way to get the current time, which is useful for measuring the time it takes to run a function. However, all of this API is hidden behind function calls, and we can&#39;t use those synchronously in Elm. Our only option to call functions from elm is to use ports. Ports are both asynchronous, one-way, and are only run after the update function is finished. So they&#39;re not a great option for measuring performance in Elm.&lt;/p&gt;
&lt;p&gt;As Elm Devs, we&#39;re stuck with the tools provided by the language. We can&#39;t use the performance API, and we can&#39;t use ports. So what can we do?&lt;/p&gt;
&lt;h2&gt;Exploring Flags and Side-Effects&lt;/h2&gt;
&lt;p&gt;Flags in Elm are super handy, they allow us to pass data into Elm from the outside world. Once it&#39;s in elm, we can decode it and use it as we please. Flags and Decoders are a fundamental feature of the language, and it&#39;s what we&#39;ll be exploiting in this hack.&lt;/p&gt;
&lt;p&gt;The tricky part of this approach is that elm decoders can only access fields. So we can&#39;t just pass in a function and call it. There&#39;s no way to have a decoder run a function... or is there?&lt;/p&gt;
&lt;p&gt;If we could somehow have some JS code run when a field on a JS object is read by Elm, we could theoretically, &amp;quot;call&amp;quot; functions from a decoder.&lt;/p&gt;
&lt;p&gt;This is where getters and proxies come in.&lt;/p&gt;
&lt;h2&gt;Getters and Proxies&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get&quot;&gt;Getters&lt;/a&gt; are a feature of JavaScript that allows us to run code when a field is read.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; author &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;firstName&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Jack&#39;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;middleInitial&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;H&#39;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;lastName&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Peterson&#39;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fullName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;firstName&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;middleInitial&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;. &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lastName&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;author&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fullName &lt;span class=&quot;token comment&quot;&gt;// Jack H. Peterson&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I guess they&#39;re typically used for the situations above. I don&#39;t know, that&#39;s the only experience I had with them prior. However, they&#39;re also useful for our purposes; They allow us to run code when a field is read.
If we had a JS object like this:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Date&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and If we ran it through a decoder like this:&lt;/p&gt;
&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token import-statement&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Json.Decode &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; JD&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token hvariable&quot;&gt;now&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JD.Value&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Float&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token hvariable&quot;&gt;now&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token hvariable&quot;&gt;JD.field&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;now&quot;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;JD.float&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We&#39;d get the exact time the field was &lt;strong&gt;accessed&lt;/strong&gt;. Because it returns the time the field was accessed, if we decoded this field later, it&#39;d show a different time! This is because the getter is running the code every time the field is accessed.&lt;/p&gt;
&lt;p&gt;The downside is we can&#39;t provide any arguments to the &amp;quot;function&amp;quot;. &lt;code&gt;Date.now()&lt;/code&gt; works because you don&#39;t need to provide any arguments, but if you did, getters would be useless.&lt;/p&gt;
&lt;p&gt;However, if we wanted to run a function that took arguments, and we didn&#39;t mind getting wacky, we could use a &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy&quot;&gt;proxy&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Proxies are a feature of JavaScript that allows us to intercept calls to an object and run code before the call is made. It&#39;s a bit like a getter, but it&#39;s more dynamic.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; handler &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;target&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; prop&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;prop&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; logger &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Proxy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; handler&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;logger&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;helloWorld &lt;span class=&quot;token comment&quot;&gt;// CONSOLE OUTPUT: helloWorld&lt;/span&gt;&lt;br /&gt;logger&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;hello world&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// CONSOLE OUTPUT: hello world&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&#39;s pretty cool, we&#39;re not only able to run code when a field is accessed. We can also access an arbitrary field! We don&#39;t need to declare upfront all the possible fields, as long as we know we want something to be logged, we can use that &amp;quot;something&amp;quot; as the field!&lt;/p&gt;
&lt;p&gt;If you passed the logger object into a decoder, you could put any String into the console.&lt;/p&gt;
&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token import-statement&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Json.Decode &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; JD&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token hvariable&quot;&gt;logger&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JD.Value&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Float&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token hvariable&quot;&gt;logger&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token hvariable&quot;&gt;JD.field&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;JD.float&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We just ran a function with arguments from an Elm decoder. Wild stuff!&lt;/p&gt;
&lt;h2&gt;The Solution&lt;/h2&gt;
&lt;h3&gt;The Shape of our JS API&lt;/h3&gt;
&lt;p&gt;What would the performance API look like if it didn&#39;t expose any functions, but instead used getters and proxies?&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; handler &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// https://github.com/elm/json/blob/1.1.3/src/Elm/Kernel/Json.js#L230&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token function&quot;&gt;has&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token comment&quot;&gt;// Elm checks if a field exists before accessing it.&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token comment&quot;&gt;// This bypasses that check by always asserting that the check is true.&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;target&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; prop&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token function-variable function&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; performance&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;mark&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;start--&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;prop&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token function-variable function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; performance&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;mark&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;end--&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;prop&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token function-variable function&quot;&gt;measure&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;&lt;br /&gt;              performance&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;measure&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;measure--&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;prop&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;start--&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;prop&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;end--&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;prop&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;target&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;type&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; proxy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Proxy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;start&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; handler&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Proxy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;end&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; handler&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;measure&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Proxy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;measure&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; handler&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; performanceAPI &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;timeOrigin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; performance&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;timeOrigin&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;measurements&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; measureEntries &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;          performance&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getEntriesByType&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;measure&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; duration&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; startTime &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; key &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;measure--&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;            measureEntries&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; startTime&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; duration &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;measureEntries&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; measureEntries&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; performance&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;toJSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; performance&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toJSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// Dynamic Marks and Measures.&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;          console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Perf Started.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; proxy&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;start&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;          console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Perf Ended.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; proxy&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;end&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;measure&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; proxy&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;measure&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;The Shape of our Elm API&lt;/h3&gt;
&lt;p&gt;What would our decoders look like if we used that wacky JS API?&lt;/p&gt;
&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token import-statement&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Json.Decode &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; JD&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token import-statement&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Result&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token hvariable&quot;&gt;perfDecoder&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JD.Decoder&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JD.Value&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token hvariable&quot;&gt;perfDecoder&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;decoder&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token hvariable&quot;&gt;JD.decodeValue&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;decoder&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Result.toMaybe&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token hvariable&quot;&gt;timeOrigin&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JD.Value&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Float&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token hvariable&quot;&gt;timeOrigin&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token hvariable&quot;&gt;JD.field&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;timeOrigin&quot;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;JD.float&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;perfDecoder&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token hvariable&quot;&gt;eventCounts&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JD.Value&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Dict&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token hvariable&quot;&gt;eventCounts&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token hvariable&quot;&gt;JD.field&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;eventCounts&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;JD.dict&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;JD.int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;perfDecoder&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Measurement&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;startTime&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;duration&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Float&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token hvariable&quot;&gt;measurements&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JD.Value&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Dict&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Measurement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token hvariable&quot;&gt;measurements&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token hvariable&quot;&gt;JD.field&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;measurements&quot;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;JD.dict&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;JD.list&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;JD.map2&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Measurement&lt;/span&gt;&lt;br /&gt;                    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;JD.field&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;startTime&quot;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;JD.float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;                    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;JD.field&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;duration&quot;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;JD.float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;perfDecoder&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token hvariable&quot;&gt;now&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JD.Value&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Float&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token hvariable&quot;&gt;now&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token hvariable&quot;&gt;JD.field&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;now&quot;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;JD.float&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;perfDecoder&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token hvariable&quot;&gt;toJSON&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JD.Value&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token hvariable&quot;&gt;toJSON&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token hvariable&quot;&gt;JD.field&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;toJSON&quot;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;JD.string&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;perfDecoder&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token hvariable&quot;&gt;internal_start&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JD.Value&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Float&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token hvariable&quot;&gt;internal_start&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;marker&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token hvariable&quot;&gt;JD.at&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;start&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;marker&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;JD.float&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;perfDecoder&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token hvariable&quot;&gt;internal_end&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JD.Value&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Float&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token hvariable&quot;&gt;internal_end&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;marker&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token hvariable&quot;&gt;JD.at&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;end&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;marker&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;JD.float&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;perfDecoder&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token hvariable&quot;&gt;internal_measure&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JD.Value&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Float&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token hvariable&quot;&gt;internal_measure&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;marker&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token hvariable&quot;&gt;JD.at&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;measure&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;marker&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;JD.float&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;perfDecoder&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;How could we use those decoders to measure performance in Elm?&lt;/p&gt;
&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token import-statement&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Json.Decode &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; JD&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token hvariable&quot;&gt;measure&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JD.Value&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;fn&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token hvariable&quot;&gt;measure&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;perf&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;tag&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token hvariable&quot;&gt;internal_start&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;tag&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;perf&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&#92;_ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&#92;&lt;span class=&quot;token hvariable&quot;&gt;passThrough&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt;&lt;br /&gt;                    _ &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;br /&gt;                        &lt;span class=&quot;token hvariable&quot;&gt;internal_end&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;tag&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;perf&lt;/span&gt;&lt;br /&gt;                            &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&#92;_ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;internal_measure&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;tag&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;perf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token hvariable&quot;&gt;passThrough&lt;/span&gt;&lt;br /&gt;           &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;{- This main function measures the duration of both the view and update function. -}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token hvariable&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Program&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JD.Value&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Msg&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token hvariable&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token hvariable&quot;&gt;Browser.element&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;init&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;init&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;br /&gt;            &#92;&lt;span class=&quot;token hvariable&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token hvariable&quot;&gt;measure&lt;/span&gt;&lt;br /&gt;                    &lt;span class=&quot;token hvariable&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;performanceApiFlagJsonValue&lt;/span&gt;&lt;br /&gt;                    &lt;span class=&quot;token string&quot;&gt;&quot;view&quot;&lt;/span&gt;&lt;br /&gt;                    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&#92;_ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;update&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;br /&gt;            &#92;&lt;span class=&quot;token hvariable&quot;&gt;msg&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token hvariable&quot;&gt;measure&lt;/span&gt;&lt;br /&gt;                    &lt;span class=&quot;token hvariable&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;performanceApiFlagJsonValue&lt;/span&gt;&lt;br /&gt;                    &lt;span class=&quot;token string&quot;&gt;&quot;update&quot;&lt;/span&gt;&lt;br /&gt;                    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&#92;_ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;update&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;msg&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;subscriptions&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &#92;_ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Sub.none&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Warnings&lt;/h2&gt;
&lt;h3&gt;Don&#39;t do this!&lt;/h3&gt;
&lt;p&gt;We&#39;re in the hacky parts of Elm here. I wouldn&#39;t be the slightest bit surprised if this approach breaks in the future. It&#39;s not a supported approach, and it&#39;s not a good idea to use this in production. It&#39;d be best if you only used this approach for debugging and performance measurement, and even then, you should be careful.&lt;/p&gt;
&lt;p&gt;It would be incredibly easy for Evan to update the Elm compiler so all JSON input is stringified and parsed before Elm could touch it. That would instantly and forever break this approach.&lt;/p&gt;
&lt;h3&gt;Proxies vs Getters&lt;/h3&gt;
&lt;p&gt;From a glance, it might seem like proxies are all-around better than getters. They&#39;re more dynamic, why don&#39;t we &lt;em&gt;JUST&lt;/em&gt; use proxies?&lt;/p&gt;
&lt;p&gt;Proxies are more complicated. Using proxies in other experiments, I&#39;ve run into memory leak issues I still don&#39;t understand. From a performance perspective, they&#39;re also significantly slower than using a getter. Getters are only marginally slower than accessing a normal object. To test it yourself, check out &lt;a href=&quot;https://codepen.io/JackHP95/pen/jOJqbzV?editors=1111&quot;&gt;this CodePen&lt;/a&gt;, and open the console.&lt;/p&gt;
&lt;p&gt;Like all things, it depends, but I&#39;d strongly recommend using getters unless you need the dynamic nature of proxies.&lt;/p&gt;
&lt;h3&gt;This post may vanish&lt;/h3&gt;
&lt;p&gt;I care about Elm more than I care about this blog post. If Evan feels this post is a problem, I will remove it.&lt;/p&gt;
&lt;p&gt;Evan, you&#39;ve created an incredible language, and I&#39;m grateful for all the work you&#39;ve put into it. If you feel this blog post is a problem, I will happily remove it. I don&#39;t want to cause you any headaches, and I don&#39;t want to cause any headaches for the community. I&#39;m just trying to share my findings and help others. If you feel this blog post is a problem, I will remove it.&lt;/p&gt;
&lt;h3&gt;You probably don&#39;t need this hack.&lt;/h3&gt;
&lt;p&gt;I&#39;ve had this proxy/getter/flag/decoder trick up my sleeve for a couple of years now, but I&#39;ve been entirely unable to think of a situation where it&#39;s necessary. I&#39;ve thought of a few situations where it might be useful, but I&#39;ve never been able to justify using it.
Maybe &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/FormData&quot;&gt;FormData&lt;/a&gt; or &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Navigator&quot;&gt;Navigator&lt;/a&gt; could be useful when wrapped in proxies and getters. The thing is, none of those REQUIRE this hack to work, you just need to call functions in the flag you&#39;re passing in or need a small port. It&#39;s way easier to do it the idiomatic way.&lt;/p&gt;
&lt;p&gt;However, this API, the Performance API, seems like it requires this hack!
So I was happy I had it stowed away, and now I&#39;m happy to share it.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Here&#39;s an Ellie App with a working example of this approach: &lt;a href=&quot;https://ellie-app.com/pYkP9NG6drWa1&quot;&gt;https://ellie-app.com/pYkP9NG6drWa1&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Measuring performance in Elm might present challenges, but leveraging getters and proxies through flags opens new avenues. Responsibly experimenting with these techniques can help identify performance bottlenecks and enhance the user experience within Elm.&lt;/p&gt;
&lt;p&gt;Remember, while this approach offers a workaround, it&#39;s essential to maintain code readability and strike a balance between optimization and maintainability.&lt;/p&gt;
&lt;p&gt;Stay curious, keep exploring, and unlock the potential of performance measurement within Elm!&lt;/p&gt;
</description>
      <pubDate>Tue, 09 Jan 2024 15:59:38 +0000</pubDate>
      <dc:creator>Jack H. Peterson</dc:creator>
      <guid>https://jackhpeterson.com/posts/0020/</guid>
    </item>
    <item>
      <title></title>
      <link>https://jackhpeterson.com/posts/0019/</link>
      <description>&lt;h1&gt;☃️ Shaking it Up&lt;/h1&gt;
&lt;p&gt;I&#39;ve been itching to get some experience with the web APIs for the gyroscope, accelerometer, and all that other Sensor stuff. I just never really had a project which was interesting and easy enough to make the juice worth the squeeze. Building a &lt;a href=&quot;https://jackhpeterson.com/s/snow-globe/&quot;&gt;Snow Globe&lt;/a&gt; was the perfect project.&lt;/p&gt;
&lt;h2&gt;🎶 Do you want to build a snow globe? 🎶&lt;/h2&gt;
&lt;p&gt;Here&#39;s the basic idea.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Setup the appropriate sensors.&lt;/li&gt;
&lt;li&gt;Monitor a for a &amp;quot;shake&amp;quot;.&lt;/li&gt;
&lt;li&gt;Fire off some &lt;a href=&quot;https://www.skypack.dev/&quot;&gt;confetti&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Polish it a bit.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Step 1 &amp;amp; 4, unsurprisingly, accounted for 95% of the work.&lt;/p&gt;
&lt;p&gt;I&#39;ll go through each step.&lt;/p&gt;
&lt;h3&gt;1) Setup the appropriate sensors.&lt;/h3&gt;
&lt;p&gt;This was rough. For whatever reason, browsers require SSL to use the sensors.
Cool. Safety. I get it. Lots of cool web stuff requires SSL.
The caveat to the SSL, is most APIs will work without SSL on localhost.
The localhost makes it possible for devs easily tinker.&lt;/p&gt;
&lt;p&gt;Here&#39;s the issue, my computer doesn&#39;t have an accelerometer for obvious reasons.
So in order to test any of this sensor stuff locally, you&#39;ll need to set up SSL for your local network.&lt;/p&gt;
&lt;p&gt;Yeesh.&lt;/p&gt;
&lt;p&gt;Thankfully, &lt;code&gt;browser-sync&lt;/code&gt; has an &lt;code&gt;--https&lt;/code&gt; flag. This is the easiest workaround.
Your browser will warn you that it&#39;s unsafe, but just blow through those warnings and your local dev setup is fine.&lt;/p&gt;
&lt;p&gt;Now you can &lt;em&gt;FINALLY&lt;/em&gt; test the sensors you&#39;re setting up.&lt;/p&gt;
&lt;p&gt;So let&#39;s talk about the APIs.&lt;/p&gt;
&lt;p&gt;The nice part of these APIs is they&#39;re all using the same foundation.
There&#39;s an unusual quirk to them though: These sensors update their local state automatically.
Totally novel for the web world. The events are just to signal that they&#39;ve updated, or that there&#39;s an error. They don&#39;t even provide the sensor data! you gotta check the sensor you created and started to get that info. Once you unlearn the patterns the rest of the platform teaches you, you&#39;re golden.&lt;/p&gt;
&lt;p&gt;I wish more web stuff worked like this. If you want to know if a button is being held, you need to monitor the &lt;code&gt;pointerdown&lt;/code&gt; and &lt;code&gt;pointerup&lt;/code&gt; events and basically maintain your own state machine.
We just put up with stuff like this. It&#39;s wild!&lt;/p&gt;
&lt;p&gt;Error handling is weird, but it&#39;s weird all over the web.&lt;/p&gt;
&lt;h3&gt;2) Monitor a for a &amp;quot;shake&amp;quot;.&lt;/h3&gt;
&lt;p&gt;Once you grok the APIs, and set up a way to output the various sensors to your screen, round the numbers, and change framerate to 1 per second, then you can start to learn what these do. You can spend 2 hours reading about these sensors, and not truly understand what it means. Hold your phone which displays the readings for 20 seconds and you&#39;ll understand how they work in 20 seconds.&lt;/p&gt;
&lt;p&gt;All of that just to say, My definition of a shake is met when the absolute values of x, y, and z from the LinearAccelerationSensor are summed together and exceed 20.
That&#39;s a convoluted sentence, and still means nothing to me, but I&#39;m happy with how it works. So that&#39;s good enough for a little tinkering project.&lt;/p&gt;
&lt;h3&gt;3) Fire off some &lt;a href=&quot;https://www.skypack.dev/&quot;&gt;confetti&lt;/a&gt;.&lt;/h3&gt;
&lt;p&gt;The homepage of skypack features a dead simple confetti package. It&#39;s great!
It&#39;s configurable, and it even has a &lt;a href=&quot;https://www.kirilv.com/canvas-confetti/#snow&quot;&gt;snow example&lt;/a&gt;.
After a little copypasta and some minor tweaks, I got the snow working nicely.
A shake would fire off confetti. It would take note of how the phone is being held and puff the snow up from the corner closest to the ground. If you shake harder, it sends the puff of snow further. I&#39;m really pleased with this Package and it was dead simple.&lt;/p&gt;
&lt;h3&gt;4) Polish it a bit.&lt;/h3&gt;
&lt;p&gt;Apple sure does think different. Their APIs are different too. 😒&lt;/p&gt;
&lt;p&gt;If you pull in a polyfill, negotiate the quirks, handle the user click requirements, and create sensible fallbacks if any of those things fail.
You too could have something that already works on desktop and android, work on iOS! It&#39;ll only take around 2-4 hours, but hey that&#39;s a small price to pay so that the most wealthy company on earth can continue to keep their browser engine options locked down and under funded.&lt;/p&gt;
&lt;p&gt;God bless &lt;a href=&quot;https://jensimmons.com/&quot;&gt;Jen Simmons&lt;/a&gt;. She has been doing a great job bringing safari into 2022 fast, but there is still a long way to go.&lt;/p&gt;
&lt;h2&gt;Give it a whirl&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://jackhpeterson.com/s/snow-globe/&quot;&gt;jackhpeterson.com/s/snow-globe/&lt;/a&gt;
That&#39;s it! It was a fun project, took me a little while longer than I would have liked, but I learned quite a few things along the way. I hope you get a kick out of it, and maybe get inspired to build your own cool little project with &lt;a href=&quot;https://whatwebcando.today/&quot;&gt;one of many, lesser known APIs the web platform provides.&lt;/a&gt;&lt;/p&gt;
</description>
      <pubDate>Tue, 09 Jan 2024 15:59:38 +0000</pubDate>
      <dc:creator>Jack H. Peterson</dc:creator>
      <guid>https://jackhpeterson.com/posts/0019/</guid>
    </item>
    <item>
      <title></title>
      <link>https://jackhpeterson.com/posts/0018/</link>
      <description>&lt;h1&gt;🗂 Why is file handing so tricky in node?&lt;/h1&gt;
&lt;p&gt;I&#39;ve been working with node and 11ty, and 11ty has been pretty nice. It abstracts away a lot of the pain-points that node.js brings to the file system. But I can&#39;t help but feel that node needs a jQuery-like API for handling files.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;blob/**/*.{html}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;blob/**/*.{md}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; file&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;file&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;dist/&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; file&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;relativeSlug &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;.html&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I mean, how nice would that be? I don&#39;t use much jQuery these days, but I think that it has a solid API, especially when working with collections. Blobs seem like the css selectors of the filesystem domain.&lt;/p&gt;
&lt;p&gt;Most files will have text. It seems like a pandoc powered plugin to normalize a ASTs could make unifying different text documents or converting formats trivial. I don&#39;t know why this doesn&#39;t exist yet. The filesystem seems like the ultimate place for a jQuery like api.&lt;/p&gt;
&lt;p&gt;I might explore this more, see what it would take to make a prototype, but if I don&#39;t I&#39;d still love for this idea to exist in some capacity somewhere. I know I&#39;d use the hell out of it.&lt;/p&gt;
</description>
      <pubDate>Tue, 09 Jan 2024 15:59:38 +0000</pubDate>
      <dc:creator>Jack H. Peterson</dc:creator>
      <guid>https://jackhpeterson.com/posts/0018/</guid>
    </item>
    <item>
      <title></title>
      <link>https://jackhpeterson.com/posts/0017/</link>
      <description>&lt;h1&gt;⛓ Daisy Chained&lt;/h1&gt;
&lt;p&gt;I love the idea of DaisyUI, but each time I try it it feels so limiting.&lt;/p&gt;
&lt;p&gt;The rediscovery of DaisyUI inspired me to redesign my website, but as I went through the redesign, I found more and more areas that DaisyUI didn&#39;t quite live up to my hopes.&lt;/p&gt;
&lt;h2&gt;Thoughts&lt;/h2&gt;
&lt;h3&gt;Utilities&lt;/h3&gt;
&lt;p&gt;First, the documentation, of the utilities is basically non-existent. It&#39;s really hard to discover what DaisyUI exposes, and how those utilities should interplay. You need to reverse engineer components to understand what utilities exist and how they work.&lt;/p&gt;
&lt;h3&gt;Components&lt;/h3&gt;
&lt;p&gt;These components are pretty opinionated on html structure, which is fine, I guess, but I tend to build non-interactive components myself to get them exactly how I want them. With interactive components, I&#39;m VERY tempted to generalize the behavior. I think with the new &lt;code&gt;:has()&lt;/code&gt; selector, making interactive components will be much more forgiving, and less-hacky. Things like the Toggle in Daisy UI are SO COOL! But I find myself only wanting a small portion of the library, and I don&#39;t think that&#39;s how DaisyUI really works. (Or at least it&#39;s not purging locally.)&lt;/p&gt;
&lt;h3&gt;Themes&lt;/h3&gt;
&lt;p&gt;They&#39;re cool, but largely impractical. Idk, I find one I like, and I stick to it.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;I think I&#39;ll be stripping it from my site soon. I need to rename some classes, redefine some components, set up some interactive CSS. But I think it&#39;ll be worth it. DaisyUI is a little too clunky for my liking, it&#39;s close to greatness, but not quite there yet.&lt;/p&gt;
</description>
      <pubDate>Tue, 09 Jan 2024 15:59:38 +0000</pubDate>
      <dc:creator>Jack H. Peterson</dc:creator>
      <guid>https://jackhpeterson.com/posts/0017/</guid>
    </item>
    <item>
      <title></title>
      <link>https://jackhpeterson.com/posts/0016/</link>
      <description>&lt;h1&gt;⬛️ Rainbow Etch Online&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://jackhpeterson.com/s/chalk&quot;&gt;Here&#39;s the link to my Rainbow Etch Experiment&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A while back I got an itch to make a scratch off rainbow sheet. It was a fun, quick, and rather easy project. Between &lt;a href=&quot;https://github.com/xiadevisser/paintpad&quot;&gt;paint-pad&lt;/a&gt;, CSS gradients, and mix-blending-modes.&lt;/p&gt;
&lt;p&gt;I&#39;d like to give a thank you to &lt;a href=&quot;https://twitter.com/steveruizok&quot;&gt;Steve Ruiz&lt;/a&gt;. This project was originally using his cool website &lt;a href=&quot;https://jackhpeterson.com/posts/0016/tldraw.com&quot;&gt;tldraw.com&lt;/a&gt; in an iframe for the canvas. He could have blocked the iframe outright, but tweeted that he planned on blocking them soon. So I had time to transition this little demo to something else.&lt;/p&gt;
</description>
      <pubDate>Tue, 09 Jan 2024 15:59:38 +0000</pubDate>
      <dc:creator>Jack H. Peterson</dc:creator>
      <guid>https://jackhpeterson.com/posts/0016/</guid>
    </item>
    <item>
      <title></title>
      <link>https://jackhpeterson.com/posts/0015/</link>
      <description>&lt;h1&gt;❤️‍🩹 Why leave a good thing behind?&lt;/h1&gt;
&lt;p&gt;I&#39;ve been cheating on my beloved website. This very one. I&#39;ve gone and built another, only to realize that I already had everything I wanted.&lt;/p&gt;
&lt;h2&gt;What I Missed&lt;/h2&gt;
&lt;h3&gt;Good Bones&lt;/h3&gt;
&lt;p&gt;I have a good file structure. It&#39;s flexible in all the right places. I feel like adding new content is a breeze.&lt;/p&gt;
&lt;h3&gt;Built right&lt;/h3&gt;
&lt;p&gt;My build setup here is SO perfect. It&#39;s very minimal. Tailwind handles the CSS, 11ty handles the HTML. I &lt;em&gt;might&lt;/em&gt; bring in esBuild to handle the JS.&lt;/p&gt;
&lt;p&gt;None of these portions are overstepping their bounds. In my new setup, I tried to combine all of these, and it&#39;s a nightmare!&lt;/p&gt;
&lt;p&gt;This site is basically sensible defaults that are easy to opt-out of. It&#39;s perfect.&lt;/p&gt;
&lt;h2&gt;Why I left&lt;/h2&gt;
&lt;p&gt;I wanted to tinker with different styles! I wanted to opt out of my CSS, explore DaisyUI. That&#39;s basically it.&lt;/p&gt;
&lt;p&gt;However, while I was tinkering with ways to reduce my pages into components, I found a couple patterns I&#39;m really digging.&lt;/p&gt;
&lt;p&gt;So I&#39;ve looted the new site of the gems it contained, and brought them back here.&lt;/p&gt;
&lt;p&gt;I&#39;ve created multiple tailwind configs, and am keeping them at a public URL.&lt;/p&gt;
&lt;p&gt;I&#39;ve building the CSS I need, when I need it.&lt;/p&gt;
&lt;p&gt;I&#39;ve reshaped a couple things on this site, but kept lofi spirit.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;🗺 Road map&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Improve 404&lt;/li&gt;
&lt;li&gt;Improve chat&lt;/li&gt;
&lt;li&gt;Improve page organization&lt;/li&gt;
&lt;li&gt;Figure out x-html/11ty plugin&lt;/li&gt;
&lt;li&gt;Improve sidebar&lt;/li&gt;
&lt;li&gt;Expose games, books, and experiments&lt;/li&gt;
&lt;li&gt;Write docs and host my OSS stuff&lt;/li&gt;
&lt;li&gt;Rework the posts/post pages&lt;/li&gt;
&lt;li&gt;Improve head tag garbage&lt;/li&gt;
&lt;li&gt;Probably remove daisy-UI themes, (maybe keep interactive parts)&lt;/li&gt;
&lt;li&gt;Expose more tailwind vars (SystemColors, Interactive Colors, CurrentBackground, Dynamic Spacing, etc)&lt;/li&gt;
&lt;/ol&gt;
</description>
      <pubDate>Tue, 09 Jan 2024 15:59:38 +0000</pubDate>
      <dc:creator>Jack H. Peterson</dc:creator>
      <guid>https://jackhpeterson.com/posts/0015/</guid>
    </item>
    <item>
      <title></title>
      <link>https://jackhpeterson.com/posts/0014/</link>
      <description>&lt;h1&gt;✍️ Ipads&lt;/h1&gt;
&lt;p&gt;I recently got an ipad and I like it quite a bit. It&#39;s fun doodling, or reading blog posts, and it&#39;s gotten me interested in building a proper blog, rss feed and the works. I don&#39;t think it needs to be anything incredible, but something simple and automatic would be great. Leaving shortform notes, or whatever would be fun. I&#39;ve really been enjoying the super casual feed &lt;a href=&quot;https://chriscoyier.net/feed/&quot;&gt;Chris Coyier&lt;/a&gt; has. It&#39;s lowkey, quick reads, and generally interesting.&lt;/p&gt;
&lt;h2&gt;The Ideal Stack&lt;/h2&gt;
&lt;p&gt;11ty, some CMS-esque thing, easy publishing, near automatic releases. It&#39;s hard to that CMS-esque thing. I&#39;ve tinkered with quite a few options, and none of them were great. However, a coworker recommended &lt;a href=&quot;https://logseq.com/&quot;&gt;logseq&lt;/a&gt; and although the logo is pretty dull, it looks incredibly powerful and simple.&lt;/p&gt;
&lt;p&gt;The scariest part about it is all the graph stuff, and my excitement to really go deep on that. It seems so cool, and really opens up a blog to be less structured in a &amp;quot;narrative&amp;quot;, since the stitching between notes is so simple and automatic. Reminds me of &lt;a href=&quot;https://en.wikipedia.org/wiki/Project_Xanadu&quot;&gt;Project Xandu by Ted Nelson&lt;/a&gt; and the original promise of Hypertext. I want to tinker with &lt;a href=&quot;https://logseq.com/&quot;&gt;logseq&lt;/a&gt;, I want to tinker with &lt;a href=&quot;https://enhance.dev/docs/&quot;&gt;enhance.dev&lt;/a&gt;, &lt;a href=&quot;https://mobile.twitter.com/zachleat/status/1563197553209856001&quot;&gt;@zachleat&lt;/a&gt; seems to be teasing 11ty 3.0. It&#39;s all so exciting and simple. All of it seems like a time sink if I&#39;m not careful.&lt;/p&gt;
</description>
      <pubDate>Tue, 09 Jan 2024 15:59:38 +0000</pubDate>
      <dc:creator>Jack H. Peterson</dc:creator>
      <guid>https://jackhpeterson.com/posts/0014/</guid>
    </item>
    <item>
      <title></title>
      <link>https://jackhpeterson.com/posts/0013/</link>
      <description>&lt;main class=&quot;flex flex-col flex-auto&quot;&gt;
    &lt;script type=&quot;module&quot; src=&quot;https://unpkg.com/@google/model-viewer/dist/model-viewer.min.js&quot;&gt;&lt;/script&gt;
    &lt;ul id=&quot;3D_houseplants&quot; style=&quot;min-height: 62vh; gap: 5%; padding: 10%&quot; class=&quot;flex flex-row items-center flex-shrink-0 overflow-x-auto overflow-y-hidden flex-grow-1&quot;&gt;
    &lt;/ul&gt;
    &lt;script&gt;
        const filenames = [
            &quot;plant1&quot;,
            &quot;plant2&quot;,
            &quot;plant3&quot;,
            &quot;plant4&quot;,
            &quot;plant5&quot;,
            &quot;plant6&quot;,
            &quot;plant7&quot;,
        ]
        const cardTemplate = (filename) =&gt; /* html */`
            &lt;li 
                id=&quot;3D_houseplant_${filename}&quot;
                style=&quot;aspect-ratio: 1/1;&quot;
                onclick=&quot;requestAnimationFrame(() =&gt; {
                    this.scrollIntoView({ inline: &#39;center&#39;, block: &#39;nearest&#39;, behavior: &#39;smooth&#39; })
                });&quot;
                class=&quot;relative z-10 flex items-center justify-center flex-shrink-0 w-4/5 max-w-lg overflow-hidden transition-all duration-500 ease-out rotate-0 bg-white border-4 shadow text-gray-500/5 rounded-2xl flex-grow-1 focus-within:rotate-45 focus-within:bg-transparent focus-within:text-gray-500/10 focus-within:overflow-visible focus-within:z-0 focus-within:shadow-none&quot;
            &gt;
            &lt;div 
                style=&quot;width:62vw;&quot;
                class=&quot;absolute flex flex-shrink-0 h-full overflow-hidden transition-all duration-500 ease-out scale-75 -translate-x-1/2 -translate-y-1/2 bg-gray-300 bg-opacity-0 rounded-none aspect-square inset-1/2 focus-within:scale-100 focus-within:-rotate-45 focus-within:bg-opacity-10 focus-within:rounded-full&quot;&gt;
                    &lt;model-viewer
                        class=&quot;flex w-full h-full&quot;
                        environment-image=&quot;/_/3d/BG.hdr&quot;
                        src=&quot;/_/3d/houseplant/${filename}.glb&quot;
                        alt=&quot;Houseplant&quot;
                        max-field-of-view=&quot;160deg&quot;
                        field-of-view=&quot;50deg&quot;
                        interaction-prompt=&quot;none&quot;
                        auto-rotate=&quot;true&quot;
                        camera-controls=&quot;true&quot;
                        shadow-intensity=&quot;1&quot;
                        loading=&quot;eager&quot;
                        interaction-policy=&quot;allow-when-focused&quot;
                        autoplay=&quot;false&quot;
                        camera-orbit=&quot;-0.42821rad 1.23488rad 100%m&quot;
                        ar-status=&quot;not-presenting&quot;
                        animation-name=&quot;undefined&quot;
                    &gt;&lt;/model-viewer&gt;
                &lt;/div&gt;
            &lt;/li&gt;
        `;
        const items = filenames.map(cardTemplate).join(&quot;&quot;);
        const $list = document.getElementById(&quot;3D_houseplants&quot;)
        $list.innerHTML = items;
    &lt;/script&gt;
    &lt;section class=&quot;py-24 mx-auto prose px-edge md:prose-lg&quot;&gt;
        &lt;h1&gt;🪴 Houseplants in 3D&lt;/h1&gt;
        &lt;p&gt;
            I&#39;ve been looking for a reason to use &lt;code&gt;&amp;lt;model-viewer&amp;gt;&lt;/code&gt; in my website. I&#39;ve also been
            itching
            to get some &quot;plants&quot; into my website. When sarah found &lt;a href=&quot;https://poly.pizza/&quot;&gt;poly.pizza&lt;/a&gt; and I
            saw a way to kill two birds with one stone!
        &lt;/p&gt;
        &lt;p&gt;The hardest part about this whole post was figuring out how to get flex to not ignore the padding on the
            right side, so silly. and I still don&#39;t fully understand why &lt;a href=&quot;https://stackoverflow.com/questions/26888428/display-flex-loses-right-padding-when-overflowing#answers-header&quot;&gt;the solution&lt;/a&gt; works.&lt;/p&gt;
    &lt;/section&gt;
&lt;/main&gt;
</description>
      <pubDate>Tue, 09 Jan 2024 15:59:38 +0000</pubDate>
      <dc:creator>Jack H. Peterson</dc:creator>
      <guid>https://jackhpeterson.com/posts/0013/</guid>
    </item>
    <item>
      <title></title>
      <link>https://jackhpeterson.com/posts/0012/</link>
      <description>&lt;main&gt;
    &lt;header class=&quot;flex flex-row flex-wrap items-center justify-center py-24 text-white bg-gray-800 gap-edge px-edge&quot;&gt;
        &lt;figure style=&quot;border-radius: 20px&quot; class=&quot;flex items-center justify-center flex-auto p-4 aspect-[4/3] bg-gradient-to-tr from-blue-400 via-purple-500 to-pink-600&quot;&gt;20px&lt;/figure&gt;
        &lt;figure style=&quot;border-radius: 20%&quot; class=&quot;flex items-center justify-center flex-auto p-4 aspect-[4/3] bg-gradient-to-tr from-blue-400 via-purple-500 to-pink-600&quot;&gt;20%&lt;/figure&gt;

        &lt;figure class=&quot;flex items-center justify-center flex-auto p-4 h-auto aspect-[4/3] icon--squircle icon bg-gradient-to-tr from-blue-400 via-purple-500 to-pink-600&quot;&gt;.squircle&lt;/figure&gt;
    &lt;/header&gt;
    &lt;section class=&quot;py-24 mx-auto prose px-edge md:prose-lg &quot;&gt;
        &lt;h1&gt;🧼 Squircles!&lt;/h1&gt;
        &lt;p&gt;I love squircles, I think they look rad. They give a friendliness that can&#39;t quite be replicated with the
            standard CSS border radius. Nonetheless they&#39;re possible in CSS and with a Utility CSS mentality and some
            SVG finesse, they&#39;re not too difficult to implement.&lt;/p&gt;
        &lt;p&gt;
            &lt;a href=&quot;https://www.simeongriggs.dev/responsive-squircles&quot;&gt;Simeon Griggs has a wonderful post on how to
                make them in CSS.&lt;/a&gt; I figured &lt;code&gt;clip-path&lt;/code&gt; was the crucial part of the puzzle, yet I didn&#39;t
            want
            to deal with figuring out how it works and what&#39;s needed to get it going, thank goodness Simeon wrote his
            lovely post to explain how it works, and how to get it working!
        &lt;/p&gt;
    &lt;/section&gt;
    
&lt;/main&gt;</description>
      <pubDate>Tue, 09 Jan 2024 15:59:38 +0000</pubDate>
      <dc:creator>Jack H. Peterson</dc:creator>
      <guid>https://jackhpeterson.com/posts/0012/</guid>
    </item>
    <item>
      <title></title>
      <link>https://jackhpeterson.com/posts/0011/</link>
      <description>&lt;main&gt;
    &lt;section class=&quot;py-24 mx-auto prose px-edge md:prose-lg &quot;&gt;
        &lt;h1&gt;📌 Bookmarklets!&lt;/h1&gt;
        &lt;p&gt;Did you know you can run javascript with a URL?&lt;/p&gt;
        &lt;p&gt;In place of a &lt;code&gt;http:&lt;/code&gt; or &lt;code&gt;https:&lt;/code&gt;, you can prefix a URL with &lt;code&gt;javascript:&lt;/code&gt;
            and it
            will evaluate the following text as JS. You&#39;ll still need to URL encode the Text, but it does provide a
            handy way to
            use JS.&lt;/p&gt;
        &lt;p&gt;Bookmarklets are a term for Bookmarks, which trigger some Javascript instead of loading a webpage.&lt;/p&gt;
        &lt;h2&gt;Some bookmarklets I use.&lt;/h2&gt;
        &lt;p&gt;Drag the Link into your bookmarks bar to use it yourself!&lt;/p&gt;
        &lt;ul&gt;
            &lt;li&gt;
                &lt;h3&gt;New Window Props&lt;/h3&gt;
                &lt;p&gt;This bookmarklet checks where your current window properties differ with the Initial window object.
                &lt;/p&gt;
                &lt;p&gt;Handy for checking what global objects are declared when adding a js script&lt;/p&gt;
                &lt;a class=&quot;bookmarklet&quot; href=&quot;javascript:(function()%7Bvar%20results%2C%20currentWindow%2Ciframe%20%3D%20document.createElement(&#39;iframe&#39;)%3Biframe.style.display%20%3D%20&#39;none&#39;%3Bdocument.body.appendChild(iframe)%3BcurrentWindow%20%3D%20Object.getOwnPropertyNames(window)%3Bresults%20%3D%20currentWindow.filter(function(prop)%20%7Breturn%20!iframe.contentWindow.hasOwnProperty(prop)%3B%7D)%3Bconsole.log(results)%3Bdocument.body.removeChild(iframe)%7D)()&quot;&gt;New Window Props&lt;/a&gt;
            &lt;/li&gt;
            &lt;li&gt;
                &lt;h3&gt;Picture in Picture Mode&lt;/h3&gt;
                &lt;p&gt;Firefox has a PIP Button overlayed on videos. Chrome does not.
                &lt;/p&gt;
                &lt;p&gt;Handy for triggering PIP mode on any webpage with a video.&lt;/p&gt;
                &lt;a class=&quot;bookmarklet&quot; href=&quot;javascript:document.querySelector(&#39;video&#39;).requestPictureInPicture();void(0);&quot;&gt;Picture-in-Picture&lt;/a&gt;
            &lt;/li&gt;
        &lt;/ul&gt;
    &lt;/section&gt;
&lt;/main&gt;
</description>
      <pubDate>Tue, 09 Jan 2024 15:59:38 +0000</pubDate>
      <dc:creator>Jack H. Peterson</dc:creator>
      <guid>https://jackhpeterson.com/posts/0011/</guid>
    </item>
    <item>
      <title></title>
      <link>https://jackhpeterson.com/posts/0010/</link>
      <description>&lt;main class=&quot;relative font-mono font-bold text-green-400 bg-green-900&quot;&gt;
    &lt;style&gt;
        .vignette {
            background: radial-gradient(closest-side, transparent, #064e3b);
        }

        .typing {
            width: 25ch;
            animation: typing 2s steps(25), blink .5s step-end infinite alternate;
            white-space: nowrap;
            overflow: hidden;
            border-right: 3px solid;
            font-family: monospace;
            font-size: 2em;
        }

        @keyframes typing {
            from {
                width: 0
            }
        }

        @keyframes blink {
            50% {
                border-color: transparent
            }
        }

    &lt;/style&gt;
    &lt;section id=&quot;face_mesh_output&quot; class=&quot;w-full h-screen&quot;&gt;
        &lt;header class=&quot;relative z-10 gap-12 py-24 font-mono px-edge max-w-prose&quot;&gt;
            &lt;h1 class=&quot;text-2xl&quot;&gt;&lt;span class=&quot;sr-only&quot;&gt;🤖&lt;/span&gt;Face Mesh Experimentation&lt;/h1&gt;
            ---------------------------------------
            &lt;p class=&quot;font-normal leading-relaxed&quot;&gt;This experiment was taken and modified from &lt;a href=&quot;https://github.com/tensorflow/tfjs-models/tree/master/face-landmarks-detection&quot;&gt;THIS PROJECT&lt;/a&gt;. This is using Tensorflow.js for the AI. I used skypack in devlopment and bundled it
                with Skypack.&lt;/p&gt;
            &lt;button type=&quot;button&quot; class=&quot;px-6 py-3 mt-4 text-green-900 bg-green-400 hover:opacity-90 focus:opacity-60&quot; id=&quot;face_mesh_activate&quot; onclick=&quot;face_mesh_initalize.classList.add(&#39;typing&#39;)&quot;&gt;Activate Face-Mesh&lt;/button&gt;
            &lt;div id=&quot;face_mesh_initalize&quot; class=&quot;z-10 w-0 my-24 overflow-hidden&quot;&gt;Initializing Face Scan...&lt;/div&gt;
        &lt;/header&gt;
        &lt;video class=&quot;absolute inset-0 w-full h-full&quot; id=&quot;face_mesh_video&quot; playsinline=&quot;&quot; style=&quot;
            -webkit-transform: scaleX(-1);
            transform: scaleX(-1);
        &quot;&gt;&lt;/video&gt;
        &lt;div class=&quot;absolute inset-0 w-full h-full vignette&quot;&gt;&lt;/div&gt;
        &lt;button type=&quot;button&quot; class=&quot;absolute inset-0 w-full h-full bg-green-900 bg-opacity-0 focus:bg-opacity-100&quot;&gt;&lt;/button&gt;
        &lt;canvas class=&quot;absolute inset-0 w-full h-full pointer-events-none&quot; id=&quot;face_mesh_canvas&quot;&gt;&lt;/canvas&gt;
    &lt;/section&gt;
    &lt;script type=&quot;module&quot;&gt;
        import { leaf } from &quot;/_/esm/util.js&quot;
        const fms = leaf(&quot;script&quot;, { type: &quot;module&quot;, src: &quot;/_/esm/face-mesh.flat.js&quot;, async: true });
        const fn = () =&gt; face_mesh_activate.before(fms);
        face_mesh_activate.addEventListener(&quot;click&quot;, fn, { once: true });
    &lt;/script&gt;
    
&lt;/main&gt;</description>
      <pubDate>Tue, 09 Jan 2024 15:59:38 +0000</pubDate>
      <dc:creator>Jack H. Peterson</dc:creator>
      <guid>https://jackhpeterson.com/posts/0010/</guid>
    </item>
    <item>
      <title></title>
      <link>https://jackhpeterson.com/posts/0009/</link>
      <description>&lt;h1&gt;😱 Emoji OMG&lt;/h1&gt;
&lt;p&gt;Pulling an emoji from text isn&#39;t super straightforward. There&#39;s no special character for emoji in regex.&lt;/p&gt;
&lt;p&gt;I&#39;d like to start replacing the favicon for the page with a favicon found in the &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; of the current section. So the first step is determining if there&#39;s an emoji in the &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; at all. However, this task is tricker than it seems. EVERYTHING online indicates the best solution is a LONG LONG string of regex which tests the unicode data.&lt;/p&gt;
&lt;p&gt;I&#39;ll do some research and see if I can find a better way to do determine if a character is regex.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;My Findings!&lt;/h2&gt;
&lt;p&gt;The typical advice you&#39;ll find online when searching for how to determine if a character is an emoji is to use &lt;code&gt;RegEx&lt;/code&gt;, but I&#39;ve found a MUCH easier way!&lt;/p&gt;
&lt;p&gt;Strings in js can be split into characters, and with the spread operator, it&#39;s easy!&lt;/p&gt;
&lt;h3&gt;Splitting a String into Chars&lt;/h3&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; string &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;🤖: Hello World! 👋&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; charList &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;string&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// [ &quot;🤖&quot;, &quot;:&quot;, &quot; &quot;, &quot;H&quot; [[...]] , &quot;d&quot;, &quot;!&quot;, &quot; &quot;, &quot;👋&quot; ]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which doesn&#39;t mean much on it&#39;s own. Frankly, it&#39;s more cumbersome to deal with. BUT! Javascript did something interesting! It didn&#39;t split up ALL the characters! As you can see from the any emoji regex example, Emojis are comprised of MANY characters! Those characters will render as a single, emoji.&lt;/p&gt;
&lt;p&gt;So JS is put in a weird position. The EXPECTED behavior of splitting a string, is accomplished. Yet, the LENGTH of each character, is technically different! Since Emojis are just unicode data rendered in a particular way, splitting a string does something fascinating in JS.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;    &lt;span class=&quot;token string&quot;&gt;&quot;🤖&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// outputs: 2&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string&quot;&gt;&quot;👋&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// outputs: 2&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string&quot;&gt;&quot;📌&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// outputs: 2&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;What it means!&lt;/h3&gt;
&lt;p&gt;Because JS splits a string by what is rendered, not by how it&#39;s represented in data, &lt;code&gt;String.length&lt;/code&gt; does something super fascinating! It will give back a value greater than 1 for emojis!&lt;/p&gt;
&lt;p&gt;With this interesting tidbit, you can determine if a character in a string is an emoji! Furthermore, you are able to use the many Array Methods to deal with the characters!&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; string &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;🤖: Hello World! 👋&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; charList &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;string&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    charList&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;some&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; char&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// charList contains an emoji&lt;/span&gt;&lt;br /&gt;    charList&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; char&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// return an array of all of the emojis in charList&lt;/span&gt;&lt;br /&gt;    charList&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; char&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// return the first emoji in charList&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I hope you found this helpful! I know it&#39;s much easier for me to deal with Emojis now.&lt;/p&gt;
</description>
      <pubDate>Tue, 09 Jan 2024 15:59:38 +0000</pubDate>
      <dc:creator>Jack H. Peterson</dc:creator>
      <guid>https://jackhpeterson.com/posts/0009/</guid>
    </item>
    <item>
      <title></title>
      <link>https://jackhpeterson.com/posts/0008/</link>
      <description>&lt;h1&gt;🥣 Ought Mealy&lt;/h1&gt;
&lt;p&gt;Some days the web seems woefully under-equipt. Today is one of those days. Here is where I bloviate so I can look up to see if I&#39;m right later.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I think a large unaddressed issue with the web is mealy machines. AKA Transitioning States.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For Example, This navbar was a bit more complex than I wished it to be because there&#39;s no way to determine scroll direction. A scroll event will take a snapshot in time and say:
&amp;quot;&amp;quot;&amp;quot;
Yes! There was a scroll! Here&#39;s my current position!
&amp;quot;&amp;quot;&amp;quot;
Gee, thanks DOM, that&#39;s mostly useless, but alright.&lt;/p&gt;
&lt;p&gt;To know scroll direction, you need to preserve state, and compare the new state to the previous state.&lt;/p&gt;
&lt;p&gt;This should be built into the browser right? I&#39;d imagine this is useful information. However, there seems to be a philosophy with the web where previous states, aren&#39;t preserved. Thus, knowing much more than X event happened, seems far more difficult than you&#39;d wish.&lt;/p&gt;
&lt;p&gt;I&#39;m not sure if I have any great insight here, This seems to be something that has been worked around, but never really through. xState has inspired much of my thought on this, but it seems to be a tool, without much opinion on how it&#39;s implemented. Perhaps having a good Library to handle State transitions, would be helpful beyond just handling events. I mean the core of adios is making changes based on data changes, if I can find a nice API to work with the entire platform and its events it could be a useful tool for building websites.&lt;/p&gt;
</description>
      <pubDate>Tue, 09 Jan 2024 15:59:38 +0000</pubDate>
      <dc:creator>Jack H. Peterson</dc:creator>
      <guid>https://jackhpeterson.com/posts/0008/</guid>
    </item>
    <item>
      <title></title>
      <link>https://jackhpeterson.com/posts/0007/</link>
      <description>&lt;main id=&quot;moire_post&quot;&gt;
    &lt;style&gt;
        #moire_post figure[class*=&quot;-moire&quot;] {
            /* filter: blur(1px) contrast(800%); */
        }

        #moire_post figure[class*=&quot;-moire&quot;]::before,
        #moire_post figure[class*=&quot;-moire&quot;]::after {
            position: absolute;
            content: &#39;&#39;;
            max-width: none;
            max-height: none;
            top: -100vmax;
            bottom: -100vmax;
            left: -100vmax;
            right: -100vmax;
        }

        #moire_post figure[class*=&quot;-moire&quot;]::after {
            will-change: transform;
            /* preflight sets these to 0 on ::before and ::after :/ */
            --tw-translate-x: inherit;
            --tw-translate-y: inherit;
            --tw-rotate: inherit;
            --tw-skew-x: inherit;
            --tw-skew-y: inherit;
            --tw-scale-x: inherit;
            --tw-scale-y: inherit;
            transform: translate(var(--tw-translate-x, 0), var(--tw-translate-y, 0)) rotate(var(--tw-rotate, 0)) skewX(var(--tw-skew-x, 0)) skewY(var(--tw-skew-y, 0)) scaleX(var(--tw-scale-x, 1)) scaleY(var(--tw-scale-y, 1))
        }

        #moire_post .radial-moire::before,
        #moire_post .radial-moire::after {
            background-image: repeating-radial-gradient(circle, currentColor, currentColor 1vmin, transparent 1vmin, transparent 2vmin);

        }

        #moire_post .grid-moire::before,
        #moire_post .grid-moire::after {
            background-image:
                repeating-linear-gradient(0deg, currentColor, currentColor 1vmin, transparent 1vmin, transparent 2vmin),
                repeating-linear-gradient(90deg, currentColor, currentColor 1vmin, transparent 1vmin, transparent 2vmin);
        }

        #moire_post .vertical-moire::before,
        #moire_post .vertical-moire::after {
            background-image:
                repeating-linear-gradient(90deg, currentColor, currentColor 1vmin, transparent 1vmin, transparent 2vmin);
        }

        #moire_post .horizontal-moire::before,
        #moire_post .horizontal-moire::after {
            background-image:
                repeating-linear-gradient(0deg, currentColor, currentColor 1vmin, transparent 1vmin, transparent 2vmin);
        }

        #moire_post .slash-moire::before,
        #moire_post .slash-moire::after {
            background-image:
                repeating-linear-gradient(10deg, currentColor, currentColor 1vmin, transparent 1vmin, transparent 2vmin);
        }

        #moire_post .speed-moire::before,
        #moire_post .speed-moire::after {
            background-image:
                repeating-linear-gradient(0deg, currentColor, currentColor 1vmin, transparent 1vmin, transparent 2vmin);
        }

    &lt;/style&gt;
    &lt;section class=&quot;py-24 mx-auto prose px-edge md:prose-lg&quot;&gt;
        &lt;h1&gt;🌕 That&#39;s a Moiré&lt;/h1&gt;
        &lt;blockquote cite=&quot;https://mathworld.wolfram.com/MoirePattern.html&quot;&gt;
            A Moiré pattern is an interference pattern produced by overlaying similar but slightly offset templates. A
            simple example is obtained by taking two identical ruled transparent sheets of plastic, superposing them,
            and rotating one about its center as the other is held fixed.
        &lt;/blockquote&gt;
        &lt;p&gt;Such a neat little phenomena. I had to whip up a little example I could play with.&lt;/p&gt;
        &lt;p&gt;Be careful, these examples can be disorienting, so proceed with caution.&lt;/p&gt;
    &lt;/section&gt;
    &lt;details&gt;
        &lt;summary class=&quot;block mx-auto text-xl max-w-max link solid flip box my-edge&quot;&gt;Click here to toggle the Moiré patterns&lt;/summary&gt;
        &lt;figure class=&quot;relative flex items-end justify-end w-full h-screen overflow-hidden snap-center radial-moire&quot; onpointermove=&quot;
            this.style.setProperty(&#39;--tw-translate-x&#39;, `${event.clientX - (this.clientWidth / 2)}px`);
            this.style.setProperty(&#39;--tw-translate-y&#39;, `${event.clientY - (this.clientHeight / 2)}px`);
        &quot;&gt;
            &lt;figcaption class=&quot;sticky z-10 px-8 m-12 font-mono text-xl font-black text-white bg-black&quot;&gt;radial-moire
            &lt;/figcaption&gt;
        &lt;/figure&gt;
        &lt;figure class=&quot;relative flex items-end justify-end w-full h-screen overflow-hidden snap-center grid-moire&quot; onpointermove=&quot;
            this.style.setProperty(&#39;--tw-rotate&#39;, `${(event.clientX /document.body.clientWidth) * 270}deg`);
        &quot;&gt;
            &lt;figcaption class=&quot;sticky z-10 px-8 m-12 font-mono text-xl font-black text-white bg-black&quot;&gt;grid-moire
            &lt;/figcaption&gt;
        &lt;/figure&gt;
        &lt;figure class=&quot;relative flex items-end justify-end w-full h-screen overflow-hidden snap-center horizontal-moire&quot; onpointermove=&quot;
            this.style.setProperty(&#39;--tw-rotate&#39;, `${(event.clientX /document.body.clientWidth) * 540}deg`);
        &quot;&gt;
            &lt;figcaption class=&quot;sticky z-10 px-8 m-12 font-mono text-xl font-black text-white bg-black&quot;&gt;horizontal-moire
            &lt;/figcaption&gt;
        &lt;/figure&gt;
        &lt;figure class=&quot;relative flex items-end justify-end w-full h-screen overflow-hidden snap-center vertical-moire&quot; onpointermove=&quot;
            this.style.setProperty(&#39;--tw-rotate&#39;, `${(event.clientX /document.body.clientWidth) * 540}deg`);
        &quot;&gt;
            &lt;figcaption class=&quot;sticky z-10 px-8 m-12 font-mono text-xl font-black text-white bg-black&quot;&gt;vertical-moire
            &lt;/figcaption&gt;
        &lt;/figure&gt;
        &lt;figure class=&quot;relative flex items-end justify-end w-full h-screen overflow-hidden snap-center slash-moire&quot; onpointermove=&quot;
            this.style.setProperty(&#39;--tw-rotate&#39;, `${(event.clientX /document.body.clientWidth) * 540}deg`);
        &quot;&gt;
            &lt;figcaption class=&quot;sticky z-10 px-8 m-12 font-mono text-xl font-black text-white bg-black&quot;&gt;slash-moire
            &lt;/figcaption&gt;
        &lt;/figure&gt;
        &lt;figure class=&quot;relative flex items-end justify-end w-full h-screen overflow-hidden snap-center speed-moire&quot; onpointermove=&quot;
            this.style.setProperty(&#39;--tw-scale-y&#39;, `${(event.clientY / this.clientHeight) + 1}`);
            this.style.setProperty(&#39;--tw-translate-y&#39;, `${event.clientY - (this.clientHeight / 2)}px`);
        &quot;&gt;
            &lt;figcaption class=&quot;sticky z-10 px-8 m-12 font-mono text-xl font-black text-white bg-black&quot;&gt;speed-moire
            &lt;/figcaption&gt;
        &lt;/figure&gt;
    &lt;/details&gt;
&lt;/main&gt;
</description>
      <pubDate>Tue, 09 Jan 2024 15:59:38 +0000</pubDate>
      <dc:creator>Jack H. Peterson</dc:creator>
      <guid>https://jackhpeterson.com/posts/0007/</guid>
    </item>
    <item>
      <title></title>
      <link>https://jackhpeterson.com/posts/0006/</link>
      <description>&lt;h1&gt;🤔 Rethinking Adios.js&lt;/h1&gt;
&lt;p&gt;For the past year or so I&#39;ve been kicking around a js library idea called adios.&lt;/p&gt;
&lt;aside&gt;Adios.js got its name from two things. First, I wanted to say goodbye to handling Imperative DOM Manipulations in JS – ala jQuery. Adios, means goodbye in spanish. Secondly, I couldn&#39;t figure out how I wanted the API to look. But I figured there were going to be parts called `is` `as` and `do` in the API. I phased most of those parts though in favor of more explicit names. So we&#39;re left with a kind of awkward name for this project.&lt;/aside&gt;
&lt;p&gt;I still think adios is a nice idea, frankly I also think the DX is okay. I built it so I know how it works, which makes the issues less frustrating. But I also think underlying adios, is a more powerful idea.&lt;/p&gt;
&lt;h2&gt;The core of Adios&lt;/h2&gt;
&lt;p&gt;Adios isn&#39;t using witchcraft or dark magic. It&#39;s using 2 well supported web APIs and the event loop. That&#39;s really it.&lt;/p&gt;
&lt;h3&gt;Mutation Observer&lt;/h3&gt;
&lt;p&gt;This is an intimidating name with a complex API. However once you get a grip on what it does, it&#39;s pretty nice. It lets you know if the DOM has changed, before the browser paints the changes.&lt;/p&gt;
&lt;h3&gt;Proxy&lt;/h3&gt;
&lt;p&gt;This has a confusing name with an API that leaves a bit to be desired. However, once you work around the shortcomings, it&#39;s pretty nice. It lets you know when an object is being interacted with and how.&lt;/p&gt;
&lt;h2&gt;What Adios Does&lt;/h2&gt;
&lt;p&gt;Adios binds data to DOM elements. By putting &lt;code&gt;data-text=&amp;quot;path.to.string&amp;quot;&lt;/code&gt; in your HTML. Adios will keep your Data and DOM in sync. Moreover, it&#39;ll PULL data from the DOM, removing the need to &amp;quot;Hydrate&amp;quot;. If anything, the DOM hydrates the Data.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Whatever, All of that was preamble.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The real nice part of adios is being able to easily create and tap into DOM and DATA events. Powered by Mutation Observers and Proxies respectively. I&#39;d like to find a way to break it into smaller pieces. I&#39;m not exactly sure what those pieces look like.&lt;/p&gt;
&lt;h2&gt;Ideas&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;I&#39;d like to&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;create attributes that respond to custom events.&lt;/li&gt;
&lt;li&gt;set up a generalized way to dispatch custom events.&lt;/li&gt;
&lt;li&gt;omit and listen for data change events.&lt;/li&gt;
&lt;li&gt;omit and listen for dom change events.&lt;/li&gt;
&lt;li&gt;keep this centralized and extensible.&lt;/li&gt;
&lt;li&gt;write basic js inline&lt;/li&gt;
&lt;li&gt;make it feel nasty to write imperative JS vs Declarative HTML.&lt;/li&gt;
&lt;/ul&gt;
</description>
      <pubDate>Tue, 09 Jan 2024 15:59:38 +0000</pubDate>
      <dc:creator>Jack H. Peterson</dc:creator>
      <guid>https://jackhpeterson.com/posts/0006/</guid>
    </item>
    <item>
      <title></title>
      <link>https://jackhpeterson.com/posts/0005/</link>
      <description>&lt;main class=&quot;flex flex-col gap-12 py-24 px-edge&quot;&gt;
    &lt;section class=&quot;mx-auto prose md:prose-lg&quot;&gt;
        &lt;h1&gt;👁 Viewport Events&lt;/h1&gt;
        &lt;q&gt;Call me crazy, I like inline events.&lt;/q&gt;
        &lt;p&gt;Inline events are nice for quick and easy events which operate upon the idea of &lt;abbr title=&quot;Locality Of Behavior&quot;&gt;LOB&lt;/abbr&gt;. It&#39;s hard to beat the ease of use. However, it seems they were largely
            abandoned. Not sure why. &lt;i&gt;I guess configuration can be strage in HTML?&lt;/i&gt;&lt;/p&gt;
        &lt;p&gt;Regardless, I whipped up this quick example to illustrate how it makes life much
            easier as a
            Utility first oriented developer.&lt;/p&gt;
        &lt;h2&gt;How It works&lt;/h2&gt;
        &lt;p&gt;I leveraged quite a few nifty Web APIs.&lt;/p&gt;
        &lt;ol&gt;
            &lt;li&gt;
                &lt;h3&gt;IntersectionObserver&lt;/h3&gt;
                &lt;p&gt;This API basically lets you know whenever an elements position on the
                    viewport has changed. As you scroll elements, if you&#39;re observing them, you
                    can determine a ton of details regarding their position. This is what we use
                    to determine if we should be firing off our custom inline events.&lt;/p&gt;
            &lt;/li&gt;
            &lt;li&gt;
                &lt;h3&gt;MutationObserver&lt;/h3&gt;
                &lt;p&gt;As you add new elements to the page, how do to make sure you&#39;re monioring
                    those elements for these custom inline events? This solves that issue, it&#39;ll
                    check every new element and attach an (Intersection)observer if relevant.
                &lt;/p&gt;
            &lt;/li&gt;
            &lt;li&gt;
                &lt;h3&gt;Function()&lt;/h3&gt;
                &lt;p&gt;Takes a string, and some arguments and turns it into real JS without some of
                    the issues things like eval, or script injection would introduce. This is
                    what makes our custom inline events work under the hood.&lt;/p&gt;
            &lt;/li&gt;
        &lt;/ol&gt;
        &lt;h2&gt;Take it for a whirl!&lt;/h2&gt;
        &lt;p&gt;Below there&#39;s a list with one &amp;lt;li.&amp;gt;. It&#39;s got a couple attributes. tailwind
            classes. An
            animate attribute which is just an attribute selector for our
            &lt;code&gt;animate.css&lt;/code&gt;
            stylesheet to target. An &lt;code&gt;on-reveal&lt;/code&gt; class which fires once when the
            element is
            brought into the viewport. An &lt;code&gt;on-view-center&lt;/code&gt; attribute which fires when
            the
            element is in the center of the screen
        &lt;/p&gt;
        &lt;p&gt;The inline &lt;code&gt;on-reveal&lt;/code&gt; code does two things. First, it loads the next
            element.
            Then, it animates itself into view via the &lt;code&gt;[animate]&lt;/code&gt; attribute.&lt;/p&gt;
        &lt;p&gt;The inline &lt;code&gt;on-view-center&lt;/code&gt; code replaces the title tag content with the
            content
            of the element.&lt;/p&gt;
    &lt;/section&gt;
    &lt;!-- &lt;script type=&quot;module&quot;&gt;
        data.go.loadNextItem = (el) =&gt; {
            const at = Number(el.textContent);
            if (at &gt;= 30) return;
            const parent = el.parentElement;
            if (parent.lastElementChild !== el) return;
            const newEl = el.cloneNode();
            newEl.innerHTML = at + 1;
            parent.append(newEl);
        };
    &lt;/script&gt; --&gt;
    &lt;ol class=&quot;gap-8 divide-y divide-gray-200&quot;&gt;
        &lt;li animate=&quot;&quot; class=&quot;items-center justify-center w-full max-w-md py-24 mx-auto text-3xl bg-white rounded&quot; on-reveal=&quot;
                data.go.loadNextItem(this); 
                this.setAttribute(&#39;animate&#39;, &#39;fade-in-bottom&#39;);
            &quot; on-view-center=&quot;_title.textContent = this.textContent&quot;&gt;
            1
        &lt;/li&gt;
    &lt;/ol&gt;
&lt;/main&gt;
</description>
      <pubDate>Tue, 09 Jan 2024 15:59:38 +0000</pubDate>
      <dc:creator>Jack H. Peterson</dc:creator>
      <guid>https://jackhpeterson.com/posts/0005/</guid>
    </item>
    <item>
      <title></title>
      <link>https://jackhpeterson.com/posts/0004/</link>
      <description>&lt;main class=&quot;flex flex-col py-24 gap-edge&quot;&gt;
    &lt;section class=&quot;mx-auto prose px-edge md:prose-lg &quot;&gt;
        &lt;h1&gt;📏 Scale Experiements&lt;/h1&gt;
        &lt;q&gt;Scales in design systems are interesting, and kinda complicated.&lt;/q&gt;
        &lt;p&gt;When designing something there are a million choices. Many of those choices are a waste of time. A design
            system is valuable because it reduces those pointless choices. There are many areas where designer need
            to make choices, Typography, Color, Composition, &lt;strong&gt;Spacing&lt;/strong&gt;, and more. Limiting spacing
            options saves time when finding the best size for an element.&lt;/p&gt;
        &lt;h2&gt;An Example&lt;/h2&gt;
        &lt;p&gt; Let&#39;s say you&#39;re dealing with an icon, and it looks good at 30, 31, and 32px. Which is the &quot;right&quot; size?
            Perhaps 30px feels right because it&#39;s a multiple of 10. Perhaps 32px feels right because it&#39;s a multiple
            of 8.
            Well, without a design system, any value is fine. Heck, 31.23px is totally fine. But in reality, You
            know what you prefer. A design system provides a rule for yourself and your team, that 31.23px, is a
            value that shouldn&#39;t be explicitly used.&lt;/p&gt;
        &lt;p&gt;But &lt;em&gt;which&lt;/em&gt; values &lt;strong&gt;should&lt;/strong&gt; be used?&lt;/p&gt;
        &lt;h2&gt;Tachyons&lt;/h2&gt;
        &lt;p&gt; &lt;a href=&quot;https://tachyons.io/&quot;&gt;Tachyons&lt;/a&gt;, (with inspiration from &lt;a href=&quot;https://twitter.com/stubbornella&quot;&gt;@stubbornella&lt;/a&gt;) uses an exponential scale.
            &lt;code&gt;2&lt;sup&gt;n&lt;/sup&gt;&lt;/code&gt;. It&#39;s pretty nice! (1,2,4,8,16,32,64,128,256,512), It&#39;s great because you&#39;ll
            never question which unit works the best. There&#39;s a literal magnitude of difference between each unit.
            The
            downside is it lacks a lot of the smaller units which are handy for smaller elements. Think &lt;a href=&quot;https://material.io/components/chips&quot;&gt;chips&lt;/a&gt;, these are much nicer when you have 2px-8px to fudge the areas between text, images, icons,
            and edges.
        &lt;/p&gt;
        &lt;h2&gt;Tailwind&lt;/h2&gt;
        &lt;p&gt;&lt;a href=&quot;https://tailwindcss.com/&quot;&gt;tailwindcss&lt;/a&gt; uses a bizzare linear system. Where each unit is 0.25rem or
            4px. Yet, these units don&#39;t increment linearly. They increment in a nonsenical sort of way. Basically
            tailwindcss doesn&#39;t have a system for saying what&#39;s included and what isn&#39;t. 30 isn&#39;t a default, but 28
            and 32 is. 40 is a default, but 38 and 42 are not. JIT, IDEs, and etc make this less of an issue, but
            it&#39;s still a strange, linear system which still expects fractions, especially at lower px values.&lt;/p&gt;
        &lt;h2&gt;My Scale&lt;/h2&gt;
        &lt;p&gt;The scale which I&#39;ve been toying with is a hybrid of the two. At work, I evaluated all of the CSS being
            used, and I found that it doesn&#39;t really fit a linear scale well, nor does it fit an exponential scale
            super well. If you were to choose a range of values near the minimum and a range of values near the max.
            You&#39;d see the gap between values is consistent, HOWEVER the size of that gap changes.&lt;/p&gt;
        &lt;p&gt;So I found a pattern which matches that pretty closely.&lt;/p&gt;
        &lt;p&gt;The scale will increment linearly in sets of 8. After a set of 8, the incrementing value is doubled. It
            sounds strange, but it works quite nicely. I&#39;m not sure if I&#39;m in love with 8. but designers do love 8.
            Perhaps 12 may work better? idk, overall the fusion of tachyons and tailwind scaling systems is pretty
            nice. I haven&#39;t been reaching for a value outside of the set, nor are there many values I&#39;d never write
            by hand. Somehow, this scale scales very nicely.&lt;/p&gt;
    &lt;/section&gt;
    &lt;output class=&quot;block max-w-full mx-auto font-mono whitespace-pre rounded p-edge bg-gray-500/5 w-max tabular-nums&quot; id=&quot;_0004_scale_output&quot;&gt;&lt;/output&gt;
    &lt;script type=&quot;module&quot;&gt;
        import { buildScale } from &quot;/_/esm/design-system.js&quot;;
        const setSize = 8
        const scale = buildScale({ setSize })();
        const format = (scale) =&gt; {
            const padEntries = ([k, v]) =&gt; String(v).padStart(4, &quot; &quot;);
            const toCells = (a = &quot;&quot;, n, i) =&gt;
                `${a}${(i - 1) % setSize ? &quot; &quot; : &quot;&#92;n&quot;}${n}`;
            return Object.entries(scale).map(padEntries).reduce(toCells);
        };

        _0004_scale_output.textContent = format(scale);
    &lt;/script&gt;
&lt;/main&gt;
</description>
      <pubDate>Tue, 09 Jan 2024 15:59:38 +0000</pubDate>
      <dc:creator>Jack H. Peterson</dc:creator>
      <guid>https://jackhpeterson.com/posts/0004/</guid>
    </item>
    <item>
      <title></title>
      <link>https://jackhpeterson.com/posts/0003/</link>
      <description>&lt;main class=&quot;flex flex-col gap-12 py-24&quot;&gt;
    &lt;style&gt;
        #var_font_list .--fw {
            font-weight: var(--fw);
            word-wrap: break-word;
        }

        #var_font_list input {
            appearance: auto;
        }

        #var_font_list .Alegreya {
            font-family: &quot;Alegreya&quot;;
        }

        #var_font_list .Antonio {
            font-family: &quot;Antonio&quot;;
        }

        #var_font_list .Archivo {
            font-family: &quot;Archivo&quot;;
        }

        #var_font_list .Arimo {
            font-family: &quot;Arimo&quot;;
        }

        #var_font_list .Asap {
            font-family: &quot;Asap&quot;;
        }

        #var_font_list .Assistant {
            font-family: &quot;Assistant&quot;;
        }

        #var_font_list .Bitter {
            font-family: &quot;Bitter&quot;;
        }

        #var_font_list .Bodoni_Moda {
            font-family: &quot;Bodoni Moda&quot;;
        }

        #var_font_list .Brygada_1918 {
            font-family: &quot;Brygada 1918&quot;;
        }

        #var_font_list .Cabin {
            font-family: &quot;Cabin&quot;;
        }

        #var_font_list .Catamaran {
            font-family: &quot;Catamaran&quot;;
        }

        #var_font_list .Caveat {
            font-family: &quot;Caveat&quot;;
        }

        #var_font_list .Changa {
            font-family: &quot;Changa&quot;;
        }

        #var_font_list .Cinzel {
            font-family: &quot;Cinzel&quot;;
        }

        #var_font_list .Comfortaa {
            font-family: &quot;Comfortaa&quot;;
        }

        #var_font_list .Commissioner {
            font-family: &quot;Commissioner&quot;;
        }

        #var_font_list .Crimson_Pro {
            font-family: &quot;Crimson Pro&quot;;
        }

        #var_font_list .Cuprum {
            font-family: &quot;Cuprum&quot;;
        }

        #var_font_list .Dancing_Script {
            font-family: &quot;Dancing Script&quot;;
        }

        #var_font_list .Domine {
            font-family: &quot;Domine&quot;;
        }

        #var_font_list .Dosis {
            font-family: &quot;Dosis&quot;;
        }

        #var_font_list .EB_Garamond {
            font-family: &quot;EB Garamond&quot;;
        }

        #var_font_list .Encode_Sans {
            font-family: &quot;Encode Sans&quot;;
        }

        #var_font_list .Epilogue {
            font-family: &quot;Epilogue&quot;;
        }

        #var_font_list .Exo {
            font-family: &quot;Exo&quot;;
        }

        #var_font_list .Exo_2 {
            font-family: &quot;Exo 2&quot;;
        }

        #var_font_list .Faustina {
            font-family: &quot;Faustina&quot;;
        }

        #var_font_list .Fira_Code {
            font-family: &quot;Fira Code&quot;;
        }

        #var_font_list .Fraunces {
            font-family: &quot;Fraunces&quot;;
        }

        #var_font_list .Grandstander {
            font-family: &quot;Grandstander&quot;;
        }

        #var_font_list .Grenze_Gotisch {
            font-family: &quot;Grenze Gotisch&quot;;
        }

        #var_font_list .Heebo {
            font-family: &quot;Heebo&quot;;
        }

        #var_font_list .Hepta_Slab {
            font-family: &quot;Hepta Slab&quot;;
        }

        #var_font_list .Ibarra_Real_Nova {
            font-family: &quot;Ibarra Real Nova&quot;;
        }

        #var_font_list .Imbue {
            font-family: &quot;Imbue&quot;;
        }

        #var_font_list .Inconsolata {
            font-family: &quot;Inconsolata&quot;;
        }

        #var_font_list .Inter {
            font-family: &quot;Inter&quot;;
        }

        #var_font_list .JetBrains_Mono {
            font-family: &quot;JetBrains Mono&quot;;
        }

        #var_font_list .Josefin_Sans {
            font-family: &quot;Josefin Sans&quot;;
        }

        #var_font_list .Josefin_Slab {
            font-family: &quot;Josefin Slab&quot;;
        }

        #var_font_list .Jost {
            font-family: &quot;Jost&quot;;
        }

        #var_font_list .Jura {
            font-family: &quot;Jura&quot;;
        }

        #var_font_list .Karla {
            font-family: &quot;Karla&quot;;
        }

        #var_font_list .Kreon {
            font-family: &quot;Kreon&quot;;
        }

        #var_font_list .Kufam {
            font-family: &quot;Kufam&quot;;
        }

        #var_font_list .Lemonada {
            font-family: &quot;Lemonada&quot;;
        }

        #var_font_list .Libre_Franklin {
            font-family: &quot;Libre Franklin&quot;;
        }

        #var_font_list .Literata {
            font-family: &quot;Literata&quot;;
        }

        #var_font_list .Lora {
            font-family: &quot;Lora&quot;;
        }

        #var_font_list .Manrope {
            font-family: &quot;Manrope&quot;;
        }

        #var_font_list .Manuale {
            font-family: &quot;Manuale&quot;;
        }

        #var_font_list .Markazi_Text {
            font-family: &quot;Markazi Text&quot;;
        }

        #var_font_list .Maven_Pro {
            font-family: &quot;Maven Pro&quot;;
        }

        #var_font_list .Merriweather_Sans {
            font-family: &quot;Merriweather Sans&quot;;
        }

        #var_font_list .Mulish {
            font-family: &quot;Mulish&quot;;
        }

        #var_font_list .MuseoModerno {
            font-family: &quot;MuseoModerno&quot;;
        }

        #var_font_list .Newsreader {
            font-family: &quot;Newsreader&quot;;
        }

        #var_font_list .Orbitron {
            font-family: &quot;Orbitron&quot;;
        }

        #var_font_list .Oswald {
            font-family: &quot;Oswald&quot;;
        }

        #var_font_list .Oxanium {
            font-family: &quot;Oxanium&quot;;
        }

        #var_font_list .Petrona {
            font-family: &quot;Petrona&quot;;
        }

        #var_font_list .Piazzolla {
            font-family: &quot;Piazzolla&quot;;
        }

        #var_font_list .Playfair_Display {
            font-family: &quot;Playfair Display&quot;;
        }

        #var_font_list .Podkova {
            font-family: &quot;Podkova&quot;;
        }

        #var_font_list .Public_Sans {
            font-family: &quot;Public Sans&quot;;
        }

        #var_font_list .Quicksand {
            font-family: &quot;Quicksand&quot;;
        }

        #var_font_list .Raleway {
            font-family: &quot;Raleway&quot;;
        }

        #var_font_list .Recursive {
            font-family: &quot;Recursive&quot;;
        }

        #var_font_list .Red_Rose {
            font-family: &quot;Red Rose&quot;;
        }

        #var_font_list .Roboto_Mono {
            font-family: &quot;Roboto Mono&quot;;
        }

        #var_font_list .Roboto_Slab {
            font-family: &quot;Roboto Slab&quot;;
        }

        #var_font_list .Rokkitt {
            font-family: &quot;Rokkitt&quot;;
        }

        #var_font_list .Rosario {
            font-family: &quot;Rosario&quot;;
        }

        #var_font_list .Rubik {
            font-family: &quot;Rubik&quot;;
        }

        #var_font_list .Ruda {
            font-family: &quot;Ruda&quot;;
        }

        #var_font_list .Saira {
            font-family: &quot;Saira&quot;;
        }

        #var_font_list .Sansita_Swashed {
            font-family: &quot;Sansita Swashed&quot;;
        }

        #var_font_list .Signika {
            font-family: &quot;Signika&quot;;
        }

        #var_font_list .Sora {
            font-family: &quot;Sora&quot;;
        }

        #var_font_list .Space_Grotesk {
            font-family: &quot;Space Grotesk&quot;;
        }

        #var_font_list .Spartan {
            font-family: &quot;Spartan&quot;;
        }

        #var_font_list .Syne {
            font-family: &quot;Syne&quot;;
        }

        #var_font_list .Texturina {
            font-family: &quot;Texturina&quot;;
        }

        #var_font_list .Trispace {
            font-family: &quot;Trispace&quot;;
        }

        #var_font_list .Truculenta {
            font-family: &quot;Truculenta&quot;;
        }

        #var_font_list .Varta {
            font-family: &quot;Varta&quot;;
        }

        #var_font_list .Vollkorn {
            font-family: &quot;Vollkorn&quot;;
        }

        #var_font_list .Work_Sans {
            font-family: &quot;Work Sans&quot;;
        }

        #var_font_list .Yanone_Kaffeesatz {
            font-family: &quot;Yanone Kaffeesatz&quot;;
        }

    &lt;/style&gt;
    &lt;section class=&quot;mx-auto prose px-edge md:prose-lg&quot;&gt;
        &lt;h1&gt;🔤 Variable Fonts&lt;/h1&gt;
        &lt;p&gt;Google fonts is great! Free, reliable, and now supports* Variable Fonts!&lt;/p&gt;
        &lt;p&gt;I&#39;ve astrixed support because there&#39;s a few big issues, from a UX perspective. SO I&#39;ll just list of a couple
            reasons why variable fonts via google are a bit rough right now. &lt;/p&gt;

        &lt;h2&gt;Issues&lt;/h2&gt;

        &lt;h3&gt;Discoverability&lt;/h3&gt;
        &lt;p&gt;First and foremost, you can&#39;t see what they all look like. There&#39;s no filter on the main fonts page for
            variable, and &lt;a href=&quot;https://fonts.google.com/variablefonts&quot;&gt;the page that shows which fonts are variable
                fonts,&lt;/a&gt; DOESN&#39;T show the fonts, it only lists them!&lt;/p&gt;

        &lt;h3&gt;No UI&lt;/h3&gt;
        &lt;p&gt;&lt;strong&gt;YOU have to handwrite the URL.&lt;/strong&gt; Between the super strange syntax, some unexpected quirks,
            andexpecting you to alphabetize their parameters. It&#39;s a headache.&lt;/p&gt;

        &lt;h3&gt;Docs are rough&lt;/h3&gt;
        &lt;p&gt;I&#39;m not super certain how to use the parameters. Weight is straighforward enough, but any other variable has
            me a bit stumped. If you know how to do it, shoot me a DM on twitter.&lt;/p&gt;

        &lt;h2&gt;Better Discoverability&lt;/h2&gt;
        &lt;p&gt;I&#39;m really only addressing discoverability here, but regardless. Below I&#39;ve listed every variable font
            available via google fonts, with a slider to change the weight of the font.&lt;/p&gt;
        &lt;p&gt;It&#39;s not much, it&#39;s imperfect, yada, yada, yada.&lt;/p&gt;
    &lt;/section&gt;
    &lt;section class=&quot;overflow-x-auto&quot;&gt;
        &lt;ul id=&quot;var_font_list&quot; class=&quot;flex flex-row gap-4 px-12 list-none py-edge&quot;&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Alegreya&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Alegreya:wght@400..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Alegreya&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Antonio&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Antonio:wght@100..700&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Antonio&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Archivo&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Archivo:wdth,wght@62..125,100..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Archivo&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Arimo&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Arimo:wght@400..700&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Arimo&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Asap&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Asap:wght@400..700&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Asap&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Assistant&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Assistant:wght@200..800&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Assistant&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Bitter&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Bitter:wght@100..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Bitter&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Bodoni_Moda&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Bodoni+Moda:opsz,wght@6..96,400..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Bodoni Moda&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Brygada_1918&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Brygada+1918:wght@400..700&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Brygada 1918&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Cabin&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Cabin:wdth,wght@75..100,400..700&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Cabin&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Catamaran&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Catamaran:wght@100..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Catamaran&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Caveat&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Caveat:wght@400..700&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Caveat&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Changa&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Changa:wght@200..800&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Changa&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Cinzel&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Cinzel:wght@400..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Cinzel&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Comfortaa&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Comfortaa:wght@300..700&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Comfortaa&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Commissioner&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Commissioner:wght@100..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Commissioner&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Crimson_Pro&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Crimson+Pro:wght@200..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Crimson Pro&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Cuprum&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Cuprum:wght@400..700&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Cuprum&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Dancing_Script&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Dancing+Script:wght@400..700&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Dancing Script&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Domine&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Domine:wght@400..700&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Domine&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Dosis&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Dosis:wght@200..800&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Dosis&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw EB_Garamond&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=EB+Garamond:wght@400..800&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;EB Garamond&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Encode_Sans&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Encode+Sans:wdth,wght@75..125,100..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Encode Sans&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Epilogue&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Epilogue:wght@100..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Epilogue&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Exo&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Exo:wght@100..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Exo&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur,
                        adipisicing elit. Eum vero consequuntur esse nihil iste dolor dolorem totam repellendus
                        voluptatum
                        eveniet
                        beatae pariatur,
                        impedit nulla minus modi ex numquam quam rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Exo_2&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Exo+2:wght@100..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Exo 2&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Faustina&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Faustina:wght@400..700&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Faustina&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Fira_Code&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Fira+Code:wght@300..700&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Fira Code&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Fraunces&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Fraunces:opsz,wght,SOFT,WONK@9..14,100..900,0..100,0..1&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Fraunces&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Grandstander&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Grandstander:wght@100..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Grandstander&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Grenze_Gotisch&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Grenze+Gotisch:wght@100..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Grenze Gotisch&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Heebo&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Heebo:wght@100..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Heebo&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Hepta_Slab&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Hepta+Slab:wght@1..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Hepta Slab&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Ibarra_Real_Nova&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Ibarra+Real%20Nova:wght@400..700&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Ibarra Real Nova&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Imbue&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Imbue:wght@100..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Imbue&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Inconsolata&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Inconsolata:wdth,wght@50..200,200..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Inconsolata&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Inter&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Inter:wght@100..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Inter&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw JetBrains_Mono&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=JetBrains+Mono:wght@100..800&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;JetBrains Mono&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Josefin_Sans&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Josefin+Sans:wght@100..700&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Josefin Sans&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Josefin_Slab&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Josefin+Slab:wght@100..700&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Josefin Slab&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Jost&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Jost:wght@100..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Jost&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Jura&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Jura:wght@300..700&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Jura&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Karla&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Karla:wght@200..800&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Karla&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Kreon&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Kreon:wght@300..700&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Kreon&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Kufam&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Kufam:wght@400..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Kufam&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Lemonada&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Lemonada:wght@300..700&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Lemonada&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Libre_Franklin&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Libre+Franklin:wght@100..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Libre Franklin&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Literata&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Literata:opsz,wght@7..72,200..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Literata&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Lora&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Lora:wght@400..700&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Lora&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Manrope&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Manrope:wght@200..800&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Manrope&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Manuale&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Manuale:wght@400..700&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Manuale&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Markazi_Text&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Markazi+Text:wght@400..700&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Markazi Text&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Maven_Pro&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Maven+Pro:wght@400..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Maven Pro&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Merriweather_Sans&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Merriweather+Sans:wght@300..800&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Merriweather Sans&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Mulish&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Mulish:wght@200..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Mulish&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw MuseoModerno&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=MuseoModerno:wght@100..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;MuseoModerno&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Newsreader&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Newsreader:opsz,wght@6..72,200..800&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Newsreader&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Orbitron&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Orbitron:wght@400..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Orbitron&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Oswald&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Oswald:wght@200..700&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Oswald&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Oxanium&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Oxanium:wght@200..800&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Oxanium&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Petrona&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Petrona:wght@100..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Petrona&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Piazzolla&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Piazzolla:opsz,wght@8..30,100..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Piazzolla&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Playfair_Display&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Playfair+Display:wght@400..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Playfair Display&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Podkova&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Podkova:wght@400..800&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Podkova&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Public_Sans&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Public+Sans:wght@100..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Public Sans&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Quicksand&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Quicksand:wght@300..700&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Quicksand&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Raleway&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Raleway:wght@100..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Raleway&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Recursive&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Recursive:wght@300..1000&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Recursive&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Red_Rose&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Red+Rose:wght@300..700&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Red Rose&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Roboto_Mono&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Roboto+Mono:wght@100..700&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Roboto Mono&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Roboto_Slab&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Roboto+Slab:wght@100..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Roboto Slab&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Rokkitt&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Rokkitt:wght@100..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Rokkitt&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Rosario&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Rosario:wght@300..700&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Rosario&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Rubik&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Rubik:wght@300..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Rubik&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Ruda&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Ruda:wght@400..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Ruda&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Saira&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Saira:wdth,wght@50..125,100..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Saira&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Sansita_Swashed&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Sansita+Swashed:wght@300..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Sansita Swashed&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Signika&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Signika:wght@300..700&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Signika&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Sora&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Sora:wght@100..800&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Sora&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Space_Grotesk&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Space+Grotesk:wght@300..700&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Space Grotesk&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Spartan&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Spartan:wght@100..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Spartan&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Syne&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Syne:wght@400..800&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Syne&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Texturina&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Texturina:wght@100..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Texturina&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Trispace&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Trispace:wdth,wght@75..125,100..800&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Trispace&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Truculenta&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Truculenta:wdth,wght@75..125,100..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Truculenta&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Varta&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Varta:wght@300..700&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Varta&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Vollkorn&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Vollkorn:wght@400..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Vollkorn&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Work_Sans&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Work+Sans:wght@100..900&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Work Sans&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
            &lt;li on-near-reveal=&quot;this.querySelector(&#39;link&#39;).disabled = false&quot; class=&quot;flex flex-col flex-none max-w-md border shadow box snap-center --fw Yanone_Kaffeesatz&quot;&gt;
                &lt;link rel=&quot;stylesheet&quot; href=&quot;https://jackhpeterson.com/__/font/css2?family=Yanone+Kaffeesatz:wght@200..700&amp;display=swap&quot; /&gt;
                &lt;article class=&quot;flex flex-col justify-center flex-auto p-4 px-4 prose md:prose-lg&quot;&gt;
                    &lt;h1&gt;Yanone Kaffeesatz&lt;/h1&gt;
                    &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eum
                        vero consequuntur esse nihil iste
                        dolor
                        dolorem
                        totam repellendus voluptatum eveniet beatae pariatur, impedit nulla minus modi ex numquam quam
                        rerum.&lt;/p&gt;
                &lt;/article&gt;
                &lt;menu class=&quot;flex items-center gap-2 p-2 m-3 bg-mute-10 rounded-lg shadow-inner&quot;&gt;
                    &lt;input type=&quot;range&quot; class=&quot;w-full m-0&quot; min=&quot;0&quot; max=&quot;900&quot; step=&quot;1&quot; oninput=&quot;this.closest(&#39;li&#39;).style.setProperty(&#39;--fw&#39;, this.value);&quot; /&gt;
                &lt;/menu&gt;
            &lt;/li&gt;
        &lt;/ul&gt;
    &lt;/section&gt;
&lt;/main&gt;
</description>
      <pubDate>Tue, 09 Jan 2024 15:59:38 +0000</pubDate>
      <dc:creator>Jack H. Peterson</dc:creator>
      <guid>https://jackhpeterson.com/posts/0003/</guid>
    </item>
    <item>
      <title></title>
      <link>https://jackhpeterson.com/posts/0002/</link>
      <description>&lt;h1&gt;💦 Spitballin&#39;&lt;/h1&gt;
&lt;h2&gt;Per page ideas&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;favicon&lt;/li&gt;
&lt;li&gt;title&lt;/li&gt;
&lt;li&gt;URL&lt;/li&gt;
&lt;li&gt;navbar text&lt;/li&gt;
&lt;li&gt;load next/last post&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;11ty could help keep data across pages easily accessible.&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;next/last blog&lt;/li&gt;
&lt;li&gt;next/last nav-layout&lt;/li&gt;
&lt;li&gt;Socials&lt;/li&gt;
&lt;li&gt;Tags&lt;/li&gt;
&lt;li&gt;RSS&lt;/li&gt;
&lt;li&gt;sitemap&lt;/li&gt;
&lt;li&gt;Adding IDs for tags!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;More obvious 11ty rationale&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;making the CSS for each post modular (namespaced)&lt;/li&gt;
&lt;li&gt;11ty could also help me convert these posts from
messy &amp;gt;pre&amp;lt; tag nonsense into proper html.&lt;/li&gt;
&lt;li&gt;Building THE actual pages for each post.
In theory this site should flow organically,
That doesn&#39;t negate the need for good links though!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Performance&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;I should host all the assets.&lt;/li&gt;
&lt;li&gt;I should JIT the tailwindcss&lt;/li&gt;
&lt;li&gt;Perhaps I should load Adios at the top of the page?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;ERA Ideas&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Check through my codepens, see if there&#39;s anything cool&lt;/li&gt;
&lt;li&gt;Container Queries would be fun to test&lt;/li&gt;
&lt;li&gt;I think it&#39;d be interesting to try using grid and span&lt;/li&gt;
&lt;/ul&gt;
</description>
      <pubDate>Tue, 09 Jan 2024 15:59:38 +0000</pubDate>
      <dc:creator>Jack H. Peterson</dc:creator>
      <guid>https://jackhpeterson.com/posts/0002/</guid>
    </item>
    <item>
      <title></title>
      <link>https://jackhpeterson.com/posts/0001/</link>
      <description>&lt;h1&gt;👋 My Site&lt;/h1&gt;
&lt;h2&gt;🤨 The Problem&lt;/h2&gt;
&lt;p&gt;I&#39;m sure you&#39;ve seen hundreds of developer sites, and thought: &lt;q&gt;Damn, I need to redesign my whole site.&lt;/q&gt; I&#39;ve gotten sick of remaking my site countless times just to have my ambition fizzle out before I ship it. I didn&#39;t want to crush my desire to rebuild my site all the time. It&#39;s hard finding a cool idea you want to explore, but finding ways to make it work with your current site, or throw it out and start over.&lt;/p&gt;
&lt;h2&gt;🥅 The Goals&lt;/h2&gt;
&lt;p&gt;There are a couple things I&#39;d like to be able to do: Allow my site to be flexible, Allow my ambition to be small, Persist old pages but most importantly, allow my site to evolve.&lt;/p&gt;
&lt;h2&gt;💡 The Idea!&lt;/h2&gt;
&lt;p&gt;It&#39;s a pretty dumb idea, but I hope it works as the site grows. Essentially, I&#39;m going to build my site as a LONG scroll. Just one big ol&#39; page in chronological order. I think normally this would be a disaster, but the web has changed, and so has my perception of it. Plus there are a bunch of great tools to assist me in this endeavor.&lt;/p&gt;
&lt;h2&gt;📐 The How&lt;/h2&gt;
&lt;p&gt;This whole concept hinges on a few web concepts.&lt;/p&gt;
&lt;h3&gt;The new CSS :where() psuedo selector&lt;/h3&gt;
&lt;p&gt;This new CSS psuedo selector can totally kill any specificity, and can scope without creating specificity issues with utility css and other more opinionated tools. If CSS is prefixed with a &lt;code&gt;:where(.namespace)&lt;/code&gt;, there shouldn&#39;t be any CSS leaking between pages.&lt;/p&gt;
&lt;h3&gt;CSS Scroll Snap&lt;/h3&gt;
&lt;p&gt;This CSS rule is nice. Think how tik-tok is just 1 LONG page full of videos. Normally that would be CHAOS and a total nightmare. However, only one video can be in frame at once, so it doesn&#39;t feel like 1 page, full of hundreds of videos, but rather 1 video per page. I hope to create that UX with this website.&lt;/p&gt;
&lt;h3&gt;HTMX&lt;/h3&gt;
&lt;p&gt;Perhaps I will use HTMX, perhaps I wont. Regardless, the perception shift HTMX created has influenced this idea. There are 3 parts where HTMX has inspired this: First, the idea of just using HTML over the wire. Second, the little on-event-attribute that fires when something rolls into view. SPA like behavior by pulling a full html document and combining it with the current html document.&lt;/p&gt;
&lt;h3&gt;TikTok&lt;/h3&gt;
&lt;p&gt;Lol, Dumb. But the UI/UX for that app is pretty neat. ALL VIDEOS EXIST ON THE SAME PAGE WHICH IS INSANE. but the scroll snap makes that point far less obvious.&lt;/p&gt;
&lt;h3&gt;The Vue3 Composition API&lt;/h3&gt;
&lt;p&gt;I don&#39;t know what to call it, It&#39;s not a Vue only idea, but was largely popularized by it. Essentailly, you just write code where it&#39;ll live. Styles/HTML/Scripts. I call it a triple, but I&#39;m not sure what it&#39;s called. Basically this pattern is ideal IMO. It&#39;s perfect for first page loads, and I find it really to reasona about. Everything lives on one file, no running from file to file, trying to understand what file, added to what build process, created the bundle output that&#39;s giving you trouble.&lt;/p&gt;
&lt;h2&gt;💫 Mix it up.&lt;/h2&gt;
&lt;p&gt;I think the scroll snapping will make multiple-pages on one scroll more approachable. :where() will give my triples, the ability to namespace without creating specificity headaches for my utilityCSS. HTMX will handle combining the individual HTML pages together client side. 11ty will take these raw triples I make, and combine them with a valid HTML template, and set up loading previous and next pages when a page is scrolled to.&lt;/p&gt;
&lt;h2&gt;👋 Conclusion&lt;/h2&gt;
&lt;p&gt;It&#39;ll likely get messy. There will be mistakes I make. but I think I can keep nav elements sticky, and allow posts to exist within those nav eras. I think this is a pretty neat idea, I&#39;m interested in exploring it, I&#39;ll keep this page updated with the progress I&#39;m making or why I&#39;ve decided to abandon it.&lt;/p&gt;
</description>
      <pubDate>Tue, 09 Jan 2024 15:59:38 +0000</pubDate>
      <dc:creator>Jack H. Peterson</dc:creator>
      <guid>https://jackhpeterson.com/posts/0001/</guid>
    </item>
  </channel>
</rss>
