<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Patrick Van der Spiegel's</title><link>http://patrick.vanderspie.gl/</link><description>Recent content on Patrick Van der Spiegel</description><generator>Hugo</generator><language>en-GB</language><lastBuildDate>Thu, 02 Jul 2026 00:00:00 +0000</lastBuildDate><atom:link href="http://patrick.vanderspie.gl/index.xml" rel="self" type="application/rss+xml"/><item><title>Ceramic Glaze Scanography</title><link>http://patrick.vanderspie.gl/posts/glaze-study/</link><pubDate>Thu, 02 Jul 2026 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/posts/glaze-study/</guid><description>&lt;p&gt;&lt;em&gt;&amp;ldquo;Glazes: Cone 6&amp;rdquo;&lt;/em&gt; by Michael Bailey contains recipes for a set of beautiful mid-fire ceramic glazes. One of those recipes is a &lt;em&gt;orange red iron glaze&lt;/em&gt;, ranging from yellow to brown and bright orange depending of the percentage of red iron oxide added to the base recipe.&lt;/p&gt;
&lt;div class="gallery" style="gap: 0.5rem;"&gt;&lt;figure class="gallery-item" style="flex-grow: 0.75;"&gt;
 &lt;img src="http://patrick.vanderspie.gl/posts/glaze-study/imgs/book1.jpg" alt="The &amp;#34;Orange red iron glazes&amp;#34; chapter of Michael Bailey&amp;#39;s book, listing the OR1 base recipe." loading="lazy" width="681" height="908" /&gt;
 &lt;div class="caption-container"&gt;&lt;figcaption&gt;The &amp;ldquo;Orange red iron glazes&amp;rdquo; chapter of Michael Bailey&amp;rsquo;s book, listing the OR1 base recipe.&lt;/figcaption&gt;&lt;/div&gt;
 &lt;/figure&gt;&lt;figure class="gallery-item" style="flex-grow: 0.75;"&gt;
 &lt;img src="http://patrick.vanderspie.gl/posts/glaze-study/imgs/book2.jpg" alt="The book&amp;#39;s test tiles showing the progression from 0% to 23% red iron oxide." loading="lazy" width="681" height="908" /&gt;
 &lt;div class="caption-container"&gt;&lt;figcaption&gt;The book&amp;rsquo;s test tiles showing the progression from 0% to 23% red iron oxide.&lt;/figcaption&gt;&lt;/div&gt;
 &lt;/figure&gt;&lt;/div&gt;

&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Ingredient&lt;/th&gt;
					&lt;th&gt;%&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Potash feldspar&lt;/td&gt;
					&lt;td&gt;46.7&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;China clay&lt;/td&gt;
					&lt;td&gt;4.0&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Bentonite&lt;/td&gt;
					&lt;td&gt;2.0&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Bone ash&lt;/td&gt;
					&lt;td&gt;15.0&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Lithium carbonate&lt;/td&gt;
					&lt;td&gt;4.0&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Talc&lt;/td&gt;
					&lt;td&gt;16.9&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Quartz&lt;/td&gt;
					&lt;td&gt;11.4&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;After preparing batches of the base glaze with various percentages of red iron oxide, we noticed that our glaze rather ranged from light to dark green and brown. The obtained colour looked great, but we were wondering &lt;em&gt;why&lt;/em&gt; our glaze gave unexpected results.&lt;/p&gt;
&lt;p&gt;










&lt;figure class=""&gt;

 &lt;div&gt;&lt;img loading="lazy" alt="Tests from a cut up cylinder with the OR1 base recipe at 1240°C, with 1 to 5% red iron oxide." src=" imgs/testers.jpg" width="1920" height="505"&gt;&lt;/div&gt;

 
 
 &lt;div class="caption-container"&gt;
 &lt;figcaption&gt; Tests from a cut up cylinder with the OR1 base recipe at 1240°C, with 1 to 5% red iron oxide. &lt;/figcaption&gt;
 &lt;/div&gt;
 
 
&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Glazes are influenced by various factors including the clay body, firing technique, and temperature of the kiln. We wondered what changes we could make to our process as to obtain results that are closer to those of the book. The book itself gave us a hint:&lt;/p&gt;
&lt;div class="quote-block"&gt;
 &lt;blockquote class="quote-content"&gt;If the glaze fires a rather plain, satin brown [&amp;hellip;] the maturing temperature can be lowered by cutting out the 4% china clay and increasing the talc [&amp;hellip;] or the feldspar [&amp;hellip;].&lt;/blockquote&gt;
&lt;/div&gt;&lt;div class="quote-source-link"&gt;
 &lt;span&gt;&amp;#34;Glazes: Cone 6&amp;#34; by Michael Bailey&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;I decided to base my ceramics graduation project on a study of OR1 glaze variants:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Cutting out china clay and &lt;strong&gt;increasing the talc&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;Cutting out china clay and &lt;strong&gt;increasing the feldspar&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;Using &lt;strong&gt;synthetic red iron oxide&lt;/strong&gt; instead of natural red iron oxide.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Other ideas included:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Using &lt;strong&gt;natron feldspar&lt;/strong&gt; instead of potash feldspar;&lt;/li&gt;
&lt;li&gt;Using &lt;strong&gt;&lt;em&gt;Bentone EW&lt;/em&gt;&lt;/strong&gt; instead of bentonite.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In the end, we saw that increasing the talc made the glaze more matte whilst increasing the feldspar made it more shiny without really having a large impact on colour. What did have an impact on colour was the clay body used and the use of &lt;strong&gt;synthetic red iron oxide&lt;/strong&gt;. By using synthetic instead of natural red iron oxide, the resulting glaze was closer to what we would expect from the book.&lt;/p&gt;
&lt;h2 id="glaze-preparation"&gt;Glaze Preparation&lt;/h2&gt;
&lt;p&gt;We numbered each of the glaze variants and gave a unique identifier based on their percentage of red iron oxide. Glazes 0&amp;ndash;19 correspond to the original recipe with natural red iron oxide ranging from 0% to 19%, 20&amp;ndash;39 correspond to the altered recipe with increased feldspar, and so on.&lt;/p&gt;
&lt;p&gt;










&lt;figure class=""&gt;

 &lt;div&gt;&lt;img loading="lazy" alt="Dozens of numbered glaze batches, each stored in their own labelled tub." src=" imgs/buckets.jpg" width="944" height="708"&gt;&lt;/div&gt;

 
 
 &lt;div class="caption-container"&gt;
 &lt;figcaption&gt; Dozens of numbered glaze batches, each stored in their own labelled tub. &lt;/figcaption&gt;
 &lt;/div&gt;
 
 
&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;For this project, I repeatedly prepared 100g of each base glaze variant and added natural or synthetic red iron oxide. Each of these recipes get their own labelled tub with glaze identifier, the recipe, and a QR code that leads to a page with examples of that glaze.&lt;/p&gt;
&lt;div class="gallery" style="gap: 0.5rem;"&gt;&lt;figure class="gallery-item" style="flex-grow: 0.7497403946002077;"&gt;
 &lt;img src="http://patrick.vanderspie.gl/posts/glaze-study/imgs/bucket_029.jpg" alt="Glaze #029: tub labelled with the recipe and a QR code to its recipe&amp;#39;s page." loading="lazy" width="722" height="963" /&gt;
 &lt;div class="caption-container"&gt;&lt;figcaption&gt;Glaze #029: tub labelled with the recipe and a QR code to its recipe&amp;rsquo;s page.&lt;/figcaption&gt;&lt;/div&gt;
 &lt;/figure&gt;&lt;figure class="gallery-item" style="flex-grow: 1.6666666666666667;"&gt;
 &lt;img src="http://patrick.vanderspie.gl/posts/glaze-study/imgs/label_029.png" alt="The printed label containing the recipe percentages and a QR code linking to that glaze&amp;#39;s recipe page." loading="lazy" width="1500" height="900" /&gt;
 &lt;div class="caption-container"&gt;&lt;figcaption&gt;The printed label containing the recipe percentages and a QR code linking to that glaze&amp;rsquo;s recipe page.&lt;/figcaption&gt;&lt;/div&gt;
 &lt;/figure&gt;&lt;/div&gt;

&lt;h2 id="test-tiles"&gt;Test Tiles&lt;/h2&gt;
&lt;p&gt;Using a paint brush, we applied these different glazes on 5x5cm test tiles of various clay bodies: we used reclaimed clay, white clay, and porcelain tiles; all fired at 1230°C or 1240°C.&lt;/p&gt;
&lt;div class="gallery" style="gap: 0.5rem;"&gt;&lt;figure class="gallery-item" style="flex-grow: 0.7497360084477297;"&gt;
 &lt;img src="http://patrick.vanderspie.gl/posts/glaze-study/imgs/porcelain.jpg" alt="Audrey Blackman porcelain, one of the clay bodies the glazes were tested on." loading="lazy" width="710" height="947" /&gt;
 &lt;div class="caption-container"&gt;&lt;figcaption&gt;Audrey Blackman porcelain, one of the clay bodies the glazes were tested on.&lt;/figcaption&gt;&lt;/div&gt;
 &lt;/figure&gt;&lt;figure class="gallery-item" style="flex-grow: 1.3333333333333333;"&gt;
 &lt;img src="http://patrick.vanderspie.gl/posts/glaze-study/imgs/bisque-tiles.jpg" alt="A tray of bisque-fired reclaimed and white clay test tiles, ready to be glazed." loading="lazy" width="1284" height="963" /&gt;
 &lt;div class="caption-container"&gt;&lt;figcaption&gt;A tray of bisque-fired reclaimed and white clay test tiles, ready to be glazed.&lt;/figcaption&gt;&lt;/div&gt;
 &lt;/figure&gt;&lt;/div&gt;

&lt;p&gt;There&amp;rsquo;s a large difference in how these test tiles look before and after firing, going from a soft pink before firing to a range from green to red afterwards.&lt;/p&gt;
&lt;div class="gallery" style="gap: 0.5rem;"&gt;&lt;figure class="gallery-item" style="flex-grow: 1.3326271186440677;"&gt;
 &lt;img src="http://patrick.vanderspie.gl/posts/glaze-study/imgs/unfired.jpg" alt="Glazed test tiles before firing." loading="lazy" width="1258" height="944" /&gt;
 &lt;div class="caption-container"&gt;&lt;figcaption&gt;Glazed test tiles before firing.&lt;/figcaption&gt;&lt;/div&gt;
 &lt;/figure&gt;&lt;figure class="gallery-item" style="flex-grow: 1.3333333333333333;"&gt;
 &lt;img src="http://patrick.vanderspie.gl/posts/glaze-study/imgs/finished-tiles.jpg" alt="Same tiles after firing, ranging from green to speckled red." loading="lazy" width="1284" height="963" /&gt;
 &lt;div class="caption-container"&gt;&lt;figcaption&gt;Same tiles after firing, ranging from green to speckled red.&lt;/figcaption&gt;&lt;/div&gt;
 &lt;/figure&gt;&lt;/div&gt;

&lt;p&gt;










&lt;figure class=""&gt;

 &lt;div&gt;&lt;img loading="lazy" alt="A spread of fired test tiles laid out on a table, together with some test cylinders and photo prints of tile scans." src=" imgs/table.jpg" width="1284" height="963"&gt;&lt;/div&gt;

 
 
 &lt;div class="caption-container"&gt;
 &lt;figcaption&gt; A spread of fired test tiles laid out on a table, together with some test cylinders and photo prints of tile scans. &lt;/figcaption&gt;
 &lt;/div&gt;
 
 
&lt;/figure&gt;&lt;/p&gt;
&lt;h3 id="splatters"&gt;Splatters&lt;/h3&gt;
&lt;p&gt;During the preparation of one of the test tiles, I accidentally spilled a drop of one glaze over the tile of another glaze, which gave a surprising effect after firing.&lt;/p&gt;
&lt;p&gt;










&lt;figure class=""&gt;

 &lt;div&gt;&lt;img loading="lazy" alt="Close-up scan from an accidental spill of one glaze over the test tile of another glaze." src=" imgs/drop.png" width="1263" height="653"&gt;&lt;/div&gt;

 
 
 &lt;div class="caption-container"&gt;
 &lt;figcaption&gt; Close-up scan from an accidental spill of one glaze over the test tile of another glaze. &lt;/figcaption&gt;
 &lt;/div&gt;
 
 
&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;I tried to replicate this afterwards with drops of high percentages red iron oxide glaze on a tile with the base recipe without any red iron oxide, but the results were not as expected:&lt;/p&gt;
&lt;div class="gallery" style="gap: 0.5rem;"&gt;&lt;figure class="gallery-item" style="flex-grow: 0.7497360084477297;"&gt;
 &lt;img src="http://patrick.vanderspie.gl/posts/glaze-study/imgs/splatter.jpg" alt="Glaze with red iron oxide splattered onto the base glaze without red iron oxide, before firing." loading="lazy" width="710" height="947" /&gt;
 &lt;div class="caption-container"&gt;&lt;figcaption&gt;Glaze with red iron oxide splattered onto the base glaze without red iron oxide, before firing.&lt;/figcaption&gt;&lt;/div&gt;
 &lt;/figure&gt;&lt;figure class="gallery-item" style="flex-grow: 1.0037339556592766;"&gt;
 &lt;img src="http://patrick.vanderspie.gl/posts/glaze-study/imgs/splatter-fired2.webp" alt="After firing, the splatter results in a light brown stain with a faint halo." loading="lazy" width="4301" height="4285" /&gt;
 &lt;div class="caption-container"&gt;&lt;figcaption&gt;After firing, the splatter results in a light brown stain with a faint halo.&lt;/figcaption&gt;&lt;/div&gt;
 &lt;/figure&gt;&lt;/div&gt;

&lt;p&gt;Because of this result, I abandoned the investigation of splatters and kept focusing on other glaze variants.&lt;/p&gt;
&lt;h2 id="test-spheres"&gt;Test Spheres&lt;/h2&gt;
&lt;p&gt;Finally, we also applied these glazes on white clay and porcelain spheres using a spray booth to see what the glaze would look like on curved surfaces.&lt;/p&gt;
&lt;div class="gallery" style="gap: 0.5rem;"&gt;&lt;figure class="gallery-item" style="flex-grow: 0.7497403946002077;"&gt;
 &lt;img src="http://patrick.vanderspie.gl/posts/glaze-study/imgs/unfired-sphere.jpg" alt="A finished sphere drying before its bisque firing." loading="lazy" width="722" height="963" /&gt;
 &lt;div class="caption-container"&gt;&lt;figcaption&gt;A finished sphere drying before its bisque firing.&lt;/figcaption&gt;&lt;/div&gt;
 &lt;/figure&gt;&lt;figure class="gallery-item" style="flex-grow: 1.3333333333333333;"&gt;
 &lt;img src="http://patrick.vanderspie.gl/posts/glaze-study/imgs/unfired-spheres.jpg" alt="Unglazed test spheres, made by press molding." loading="lazy" width="1284" height="963" /&gt;
 &lt;div class="caption-container"&gt;&lt;figcaption&gt;Unglazed test spheres, made by press molding.&lt;/figcaption&gt;&lt;/div&gt;
 &lt;/figure&gt;&lt;figure class="gallery-item" style="flex-grow: 0.7497360084477297;"&gt;
 &lt;img src="http://patrick.vanderspie.gl/posts/glaze-study/imgs/spheres-fired.jpg" alt="Glazed and fired spheres." loading="lazy" width="710" height="947" /&gt;
 &lt;div class="caption-container"&gt;&lt;figcaption&gt;Glazed and fired spheres.&lt;/figcaption&gt;&lt;/div&gt;
 &lt;/figure&gt;&lt;/div&gt;

&lt;h2 id="glaze-scanography"&gt;Glaze Scanography&lt;/h2&gt;
&lt;p&gt;A large part of this work was tile scanning on a &lt;em&gt;Canon CanoScan LiDE 210&lt;/em&gt; flatbed scanner to obtain a close-up of each test tile.&lt;/p&gt;
&lt;div class="gallery" style="gap: 0.5rem;"&gt;&lt;figure class="gallery-item" style="flex-grow: 1;"&gt;
 &lt;img src="http://patrick.vanderspie.gl/posts/glaze-study/imgs/closeup1.webp" alt="Bright red flowers, faintly looks like &amp;#34;mocha diffusion&amp;#34;." loading="lazy" width="2000" height="2000" /&gt;
 &lt;div class="caption-container"&gt;&lt;figcaption&gt;Bright red flowers, faintly looks like &amp;ldquo;mocha diffusion&amp;rdquo;.&lt;/figcaption&gt;&lt;/div&gt;
 &lt;/figure&gt;&lt;figure class="gallery-item" style="flex-grow: 1;"&gt;
 &lt;img src="http://patrick.vanderspie.gl/posts/glaze-study/imgs/closeup2.webp" alt="Black speckles across a red background." loading="lazy" width="2000" height="2000" /&gt;
 &lt;div class="caption-container"&gt;&lt;figcaption&gt;Black speckles across a red background.&lt;/figcaption&gt;&lt;/div&gt;
 &lt;/figure&gt;&lt;figure class="gallery-item" style="flex-grow: 1;"&gt;
 &lt;img src="http://patrick.vanderspie.gl/posts/glaze-study/imgs/closeup3.webp" alt="Olive surface with tiny speckles and crazing." loading="lazy" width="2000" height="2000" /&gt;
 &lt;div class="caption-container"&gt;&lt;figcaption&gt;Olive surface with tiny speckles and crazing.&lt;/figcaption&gt;&lt;/div&gt;
 &lt;/figure&gt;&lt;/div&gt;

&lt;p&gt;










&lt;figure class=""&gt;

 &lt;div&gt;&lt;img loading="lazy" alt="Overview of the scanned glaze tiles." src=" imgs/all-tiles.webp" width="7470" height="4980"&gt;&lt;/div&gt;

 
 
 &lt;div class="caption-container"&gt;
 &lt;figcaption&gt; Overview of the scanned glaze tiles. &lt;/figcaption&gt;
 &lt;/div&gt;
 
 
&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;All tiles are visible &lt;a href="http://patrick.vanderspie.gl/ceramics/or-glaze/"&gt;here&lt;/a&gt;. Each scan links to its own recipe page, where you can see the recipe and other scans of the same glaze.&lt;/p&gt;
&lt;p&gt;Some tiles are not perfectly flat and thus some spots look blurry when scanned because of a lacking &lt;a href="http://www.microscopy-uk.org.uk/mag/artjan13/dw-scanner-type.html"&gt;depth of field&lt;/a&gt; of my flatbed scanner. This is especially visible at the edges of the tile. I&amp;rsquo;d love to replicate these scans on a CCD scanner and see if tile edges turn out sharper.&lt;/p&gt;
&lt;p&gt;










&lt;figure class=""&gt;

 &lt;div&gt;&lt;img loading="lazy" alt="Blurry edge of a test tile on scan, which I assume is due to the lacking depth of field of the flatbed scanner." src=" imgs/blurry-edge.png" width="839" height="247"&gt;&lt;/div&gt;

 
 
 &lt;div class="caption-container"&gt;
 &lt;figcaption&gt; Blurry edge of a test tile on scan, which I assume is due to the lacking depth of field of the flatbed scanner. &lt;/figcaption&gt;
 &lt;/div&gt;
 
 
&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id="projection"&gt;Projection&lt;/h2&gt;
&lt;p&gt;I initially wanted to display the tile scans using a cheap second-hand &lt;em&gt;Elmo Omnigraphic 252&lt;/em&gt;, a &lt;a href="https://en.wikipedia.org/wiki/Carousel_slide_projector"&gt;carrousel slide projector&lt;/a&gt;. This specific model sadly does not have a built-in timer. Some shops sell universal interval timers which seem compatible with the projector, but these go for several times the price I paid for the projector itself.&lt;/p&gt;
&lt;div class="gallery" style="gap: 0.5rem;"&gt;&lt;figure class="gallery-item" style="flex-grow: 0.5625;"&gt;
 &lt;img src="http://patrick.vanderspie.gl/posts/glaze-study/imgs/slides.jpg" alt="Tile scans mounted as 35mm slides, held up to the light." loading="lazy" width="720" height="1280" /&gt;
 &lt;div class="caption-container"&gt;&lt;figcaption&gt;Tile scans mounted as 35mm slides, held up to the light.&lt;/figcaption&gt;&lt;/div&gt;
 &lt;/figure&gt;&lt;figure class="gallery-item" style="flex-grow: 1.3337950138504155;"&gt;
 &lt;img src="http://patrick.vanderspie.gl/posts/glaze-study/imgs/tile-projection.jpg" alt="A single tile projected using the &amp;#34;Elmo Omnigraphic 252&amp;#34; carrousel slide projector." loading="lazy" width="963" height="722" /&gt;
 &lt;div class="caption-container"&gt;&lt;figcaption&gt;A single tile projected using the &amp;ldquo;Elmo Omnigraphic 252&amp;rdquo; carrousel slide projector.&lt;/figcaption&gt;&lt;/div&gt;
 &lt;/figure&gt;&lt;/div&gt;

&lt;p&gt;I created my own WiFi-enabled timer allowing me to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Manually, but remotely, cycle through my slides;&lt;/li&gt;
&lt;li&gt;Automatically cycle through all the slides of the tray;&lt;/li&gt;
&lt;li&gt;Change the time interval of this cycling.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I tackled this project using a &lt;em&gt;Wemos D1 Mini&lt;/em&gt;, soldering a 6-pin DIN connector, and struggling to make a basic electronics circuit containing a relay, diode, and transistor on a breadboard. This worked (and I learned a lot in the process), but in the end I had to abandon the idea of using slides for the presentation of my work because of time and budget constraints: the cost of ordering 80 slides with express delivery was not worth the novelty of using this slide projector.&lt;/p&gt;
&lt;video controls loop muted playsinline style="width: 100%; max-width: 22rem; display: block; margin-inline: auto;"&gt;
 &lt;source src="imgs/slide-projection.mp4" type="video/mp4"&gt;
&lt;/video&gt;

&lt;p&gt;Instead of going for the slide projector, I opted to create a moving image from a handful of scans by zooming in and sliding over the image. This video could then be displayed using a &lt;a href="https://www.agptek.com/product/agptek-mini-1080p-full-hd-digital-drives-de/"&gt;small media player&lt;/a&gt; connected to a beamer over HDMI.&lt;/p&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
			&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/5Y8zc-BBXr4?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
		&lt;/div&gt;

&lt;p&gt;










&lt;figure class=""&gt;

 &lt;div&gt;&lt;img loading="lazy" alt="The close-up tile scan video projected on a roll up projector screen." src=" imgs/beamer.jpg" width="1284" height="963"&gt;&lt;/div&gt;

 
 
 &lt;div class="caption-container"&gt;
 &lt;figcaption&gt; The close-up tile scan video projected on a roll up projector screen. &lt;/figcaption&gt;
 &lt;/div&gt;
 
 
&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id="exposition"&gt;Exposition&lt;/h2&gt;
&lt;div class="gallery" style="gap: 0.5rem;"&gt;&lt;figure class="gallery-item" style="flex-grow: 0.7497403946002077;"&gt;
 &lt;img src="http://patrick.vanderspie.gl/posts/glaze-study/imgs/expo1.jpg" alt="View from the exposition space, with cabinets and the tile scan video projected at the back." loading="lazy" width="722" height="963" /&gt;
 &lt;div class="caption-container"&gt;&lt;figcaption&gt;View from the exposition space, with cabinets and the tile scan video projected at the back.&lt;/figcaption&gt;&lt;/div&gt;
 &lt;/figure&gt;&lt;figure class="gallery-item" style="flex-grow: 1.3333333333333333;"&gt;
 &lt;img src="http://patrick.vanderspie.gl/posts/glaze-study/imgs/expo2.jpg" alt="The projected close-up video, flanked by display cabinets of the scanned test tiles and glazed spheres and prints from scans on the side wall." loading="lazy" width="1284" height="963" /&gt;
 &lt;div class="caption-container"&gt;&lt;figcaption&gt;The projected close-up video, flanked by display cabinets of the scanned test tiles and glazed spheres and prints from scans on the side wall.&lt;/figcaption&gt;&lt;/div&gt;
 &lt;/figure&gt;&lt;/div&gt;

&lt;div class="gallery" style="gap: 0.5rem;"&gt;&lt;figure class="gallery-item" style="flex-grow: 0.7497403946002077;"&gt;
 &lt;img src="http://patrick.vanderspie.gl/posts/glaze-study/imgs/tiles1.jpg" alt="Test tiles of recipe variants in a display cabinet." loading="lazy" width="722" height="963" /&gt;
 &lt;div class="caption-container"&gt;&lt;figcaption&gt;Test tiles of recipe variants in a display cabinet.&lt;/figcaption&gt;&lt;/div&gt;
 &lt;/figure&gt;&lt;figure class="gallery-item" style="flex-grow: 0.7497403946002077;"&gt;
 &lt;img src="http://patrick.vanderspie.gl/posts/glaze-study/imgs/spheres.jpg" alt="Glazed spheres in a display cabinet." loading="lazy" width="722" height="963" /&gt;
 &lt;div class="caption-container"&gt;&lt;figcaption&gt;Glazed spheres in a display cabinet.&lt;/figcaption&gt;&lt;/div&gt;
 &lt;/figure&gt;&lt;figure class="gallery-item" style="flex-grow: 0.7497403946002077;"&gt;
 &lt;img src="http://patrick.vanderspie.gl/posts/glaze-study/imgs/tiles2.jpg" alt="Test tiles of recipe variants in a display cabinet." loading="lazy" width="722" height="963" /&gt;
 &lt;div class="caption-container"&gt;&lt;figcaption&gt;Test tiles of recipe variants in a display cabinet.&lt;/figcaption&gt;&lt;/div&gt;
 &lt;/figure&gt;&lt;/div&gt;

&lt;div class="gallery" style="gap: 0.5rem;"&gt;&lt;figure class="gallery-item" style="flex-grow: 1.3336683417085426;"&gt;
 &lt;img src="http://patrick.vanderspie.gl/posts/glaze-study/imgs/prints.jpg" alt="Large-format prints of individual tile scans." loading="lazy" width="1327" height="995" /&gt;
 &lt;div class="caption-container"&gt;&lt;figcaption&gt;Large-format prints of individual tile scans.&lt;/figcaption&gt;&lt;/div&gt;
 &lt;/figure&gt;&lt;figure class="gallery-item" style="flex-grow: 0.749748743718593;"&gt;
 &lt;img src="http://patrick.vanderspie.gl/posts/glaze-study/imgs/prints2.jpg" alt="A print of the full grid of scanned tiles, arranged from pale to dark." loading="lazy" width="746" height="995" /&gt;
 &lt;div class="caption-container"&gt;&lt;figcaption&gt;A print of the full grid of scanned tiles, arranged from pale to dark.&lt;/figcaption&gt;&lt;/div&gt;
 &lt;/figure&gt;&lt;/div&gt;
</description></item><item><title>"Current Trends" guest lecture</title><link>http://patrick.vanderspie.gl/posts/current-trends/</link><pubDate>Wed, 06 May 2026 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/posts/current-trends/</guid><description>&lt;hr class="slide-sep" id="01"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-01.svg" alt="Slide 01" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="02"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-02.svg" alt="Slide 02" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="03"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-03.svg" alt="Slide 03" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;p&gt;You can find the &lt;code&gt;pbsf-lib&lt;/code&gt; Python module on &lt;a href="https://github.com/pvdsp/pbsf-lib"&gt;GitHub&lt;/a&gt;; follow the &lt;a href="https://github.com/pvdsp/pbsf-lib#installation"&gt;installation instructions&lt;/a&gt; in the &lt;code&gt;README.md&lt;/code&gt;.&lt;/p&gt;
&lt;hr class="slide-sep" id="04"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-04.svg" alt="Slide 04" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="05"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-05.svg" alt="Slide 05" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;p&gt;In this introduction, we focus on &lt;strong&gt;univariate time series&lt;/strong&gt;.&lt;/p&gt;
&lt;hr class="slide-sep" id="06"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-06.svg" alt="Slide 06" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;p&gt;In the example above, we look at the total load on the Belgian grid over time. You can find this data at &lt;strong&gt;&lt;a href="https://opendata.elia.be"&gt;opendata.elia.be&lt;/a&gt;&lt;/strong&gt;. We see some &lt;a href="https://en.wikipedia.org/wiki/Seasonality"&gt;seasonality&lt;/a&gt;: the load on the grid is generally higher in the colder months, and drops during the warmer months.&lt;/p&gt;
&lt;hr class="slide-sep" id="07"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-07.svg" alt="Slide 07" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;p&gt;Zooming in on just one month, we see a repeating pattern of higher load during workdays and lower load during weekends.&lt;/p&gt;
&lt;hr class="slide-sep" id="08"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-08.svg" alt="Slide 08" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;p&gt;Overlapping all workdays of September, we see the rise in load between 3 and 6 AM, with a small dip in load around noon, and a gradual drop throughout the evening.&lt;/p&gt;
&lt;hr class="slide-sep" id="09"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-09.svg" alt="Slide 09" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="10"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-10.svg" alt="Slide 10" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;p&gt;










&lt;figure class=""&gt;

 &lt;div&gt;&lt;img loading="lazy" alt="" src=" imgs/sliding_window-animation.png" width="1000" height="350"&gt;&lt;/div&gt;

 
 
 
&lt;/figure&gt;&lt;/p&gt;
&lt;hr class="slide-sep" id="11"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-11.svg" alt="Slide 11" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="13"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-13.svg" alt="Slide 13" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="14"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-14.svg" alt="Slide 14" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="15"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-15.svg" alt="Slide 15" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="16"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-16.svg" alt="Slide 16" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;p&gt;










&lt;figure class=""&gt;

 &lt;div&gt;&lt;img loading="lazy" alt="" src=" imgs/distance_profile-animation.png" width="1200" height="700"&gt;&lt;/div&gt;

 
 
 
&lt;/figure&gt;&lt;/p&gt;
&lt;hr class="slide-sep" id="17"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-17.svg" alt="Slide 17" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="18"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-18.svg" alt="Slide 18" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="19"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-19.svg" alt="Slide 19" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="20"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-20.svg" alt="Slide 20" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="21"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-21.svg" alt="Slide 21" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="22"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-22.svg" alt="Slide 22" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="23"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-23.svg" alt="Slide 23" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="24"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-24.svg" alt="Slide 24" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="25"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-25.svg" alt="Slide 25" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="26"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-26.svg" alt="Slide 26" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;p&gt;See &lt;em&gt;&lt;a href="https://youtu.be/LnQneYvg84M"&gt;&amp;ldquo;Time Series Data Mining Using the Matrix Profile&amp;rdquo;&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;hr class="slide-sep" id="27"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-27.svg" alt="Slide 27" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="28"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-28.svg" alt="Slide 28" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="29"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-29.svg" alt="Slide 29" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="30"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-30.svg" alt="Slide 30" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="31"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-31.svg" alt="Slide 31" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="32"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-32.svg" alt="Slide 32" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="33"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-33.svg" alt="Slide 33" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="34"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-34.svg" alt="Slide 34" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="35"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-35.svg" alt="Slide 35" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="36"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-36.svg" alt="Slide 36" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;p&gt;&lt;hr class="slide-sep" id="37"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-37.svg" alt="Slide 37" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

The more fine-grained the representation, the more accurate the distance approximation.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;










&lt;figure class=""&gt;

 &lt;div&gt;&lt;img loading="lazy" alt="" src=" imgs/distance_anim_paa_2.png" width="1200" height="700"&gt;&lt;/div&gt;

 
 
 
&lt;/figure&gt;











&lt;figure class=""&gt;

 &lt;div&gt;&lt;img loading="lazy" alt="" src=" imgs/distance_anim_paa_8.png" width="1200" height="700"&gt;&lt;/div&gt;

 
 
 
&lt;/figure&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;










&lt;figure class=""&gt;

 &lt;div&gt;&lt;img loading="lazy" alt="" src=" imgs/distance_anim_pla_2.png" width="1200" height="700"&gt;&lt;/div&gt;

 
 
 
&lt;/figure&gt;











&lt;figure class=""&gt;

 &lt;div&gt;&lt;img loading="lazy" alt="" src=" imgs/distance_anim_pla_8.png" width="1200" height="700"&gt;&lt;/div&gt;

 
 
 
&lt;/figure&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;










&lt;figure class=""&gt;

 &lt;div&gt;&lt;img loading="lazy" alt="" src=" imgs/distance_anim_sax_2.png" width="1200" height="700"&gt;&lt;/div&gt;

 
 
 
&lt;/figure&gt;











&lt;figure class=""&gt;

 &lt;div&gt;&lt;img loading="lazy" alt="" src=" imgs/distance_anim_sax_8.png" width="1200" height="700"&gt;&lt;/div&gt;

 
 
 
&lt;/figure&gt;&lt;/p&gt;
&lt;hr class="slide-sep" id="44"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-44.svg" alt="Slide 44" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr&gt;
&lt;p&gt;










&lt;figure class=""&gt;

 &lt;div&gt;&lt;img loading="lazy" alt="" src=" imgs/distance_anim_sax_a32.png" width="1200" height="700"&gt;&lt;/div&gt;

 
 
 
&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Increasing the &lt;code&gt;alphabet_size&lt;/code&gt; solves the issue.&lt;/p&gt;
&lt;p&gt;&lt;hr class="slide-sep" id="46"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-46.svg" alt="Slide 46" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

See &lt;em&gt;&lt;a href="https://link.springer.com/book/10.1007/3-540-44565-X"&gt;&amp;ldquo;Sequence Learning: Paradigms, Algorithms, and Applications&amp;rdquo;&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;hr class="slide-sep" id="47"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-47.svg" alt="Slide 47" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="48"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-48.svg" alt="Slide 48" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="49"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-49.svg" alt="Slide 49" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="50"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-50.svg" alt="Slide 50" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="51"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-51.svg" alt="Slide 51" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="55"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-55.svg" alt="Slide 55" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;p&gt;See &lt;em&gt;&lt;a href="https://ieeexplore.ieee.org/abstract/document/9537291"&gt;&amp;ldquo;Current Time Series Anomaly Detection Benchmarks are Flawed and are Creating the Illusion of Progress&amp;rdquo;&lt;/a&gt;&lt;/em&gt; by Renjie Wu and Eamonn J. Keogh.&lt;/p&gt;
&lt;hr class="slide-sep" id="56"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-56.svg" alt="Slide 56" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="57"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-57.svg" alt="Slide 57" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="58"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-58.svg" alt="Slide 58" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="59"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-59.svg" alt="Slide 59" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;video controls loop muted playsinline style="width: 100%; max-width: 100%; display: block; margin-inline: auto;"&gt;
 &lt;source src="imgs/demo.mp4" type="video/mp4"&gt;
&lt;/video&gt;

&lt;hr class="slide-sep" id="60"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-60.svg" alt="Slide 60" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="61"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-61.svg" alt="Slide 61" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="62"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-62.svg" alt="Slide 62" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="63"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-63.svg" alt="Slide 63" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="64"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-64.svg" alt="Slide 64" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="65"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-65.svg" alt="Slide 65" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;p&gt;Note that the &lt;code&gt;SlopeSignNode&lt;/code&gt; is just an example to explain the concept of an approximation. It generally performs poorly in approximating and comparing most time series segments. Other approximations implement a distance that lower bounds the Euclidean distance.&lt;/p&gt;
&lt;hr class="slide-sep" id="66"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-66.svg" alt="Slide 66" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="67"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-67.svg" alt="Slide 67" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;hr class="slide-sep" id="68"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-68.svg" alt="Slide 68" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;p&gt;See &lt;em&gt;&lt;a href="https://www.sciencedirect.com/science/article/pii/S0140366422002298"&gt;&amp;ldquo;Hierarchical pattern matching for anomaly detection in time series&amp;rdquo;&lt;/a&gt;&lt;/em&gt; by M. Van Onsem et al.&lt;/p&gt;
&lt;hr class="slide-sep" id="69"&gt;
&lt;figure class="slide"&gt;
 &lt;img src="slides/slide-69.svg" alt="Slide 69" loading="lazy" width="1440" height="810" /&gt;
&lt;/figure&gt;

&lt;p&gt;See the &lt;a href="https://github.com/pvdsp/pbsf-lib/tree/main#visualising-results"&gt;&lt;code&gt;pbsf-lib&lt;/code&gt; documentation&lt;/a&gt; on how to visualise results.&lt;/p&gt;
&lt;hr&gt;</description></item><item><title>Maasmarathon</title><link>http://patrick.vanderspie.gl/notes/2026-05-03/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/notes/2026-05-03/</guid><description>&lt;div class="fitroute"&gt;
 &lt;figure class="light"&gt;
 &lt;img src="http://patrick.vanderspie.gl/notes/2026-05-03/route.png" alt="Maasmarathon route" loading="lazy" /&gt;
 &lt;/figure&gt;
 &lt;figure class="dark"&gt;
 &lt;img src="http://patrick.vanderspie.gl/notes/2026-05-03/route-dark.png" alt="Maasmarathon route" loading="lazy" /&gt;
 &lt;/figure&gt;&lt;div class="fitroute-chips"&gt;
 &lt;div class="fitroute-chip"&gt;
 &lt;span class="fitroute-label"&gt;Distance&lt;/span&gt;
 &lt;span class="fitroute-value"&gt;42.99 km&lt;/span&gt;
 &lt;/div&gt;
 &lt;div class="fitroute-chip"&gt;
 &lt;span class="fitroute-label"&gt;Moving time&lt;/span&gt;
 &lt;span class="fitroute-value"&gt;3:59:09&lt;/span&gt;
 &lt;/div&gt;
 &lt;div class="fitroute-chip"&gt;
 &lt;span class="fitroute-label"&gt;Elevation&lt;/span&gt;
 &lt;span class="fitroute-value"&gt;273 m&lt;/span&gt;
 &lt;/div&gt;
 &lt;/div&gt;&lt;hr class="hr-subtle" /&gt;
&lt;/div&gt;

&lt;style&gt;
.hr-subtle {
 background: rgba(0, 0, 0, 0.08);
 margin: 1em 0 1.5em;
}
html.dark .hr-subtle {
 background: rgba(255, 255, 255, 0.08);
}
@media (prefers-color-scheme: dark) {
 html:not(.dark):not(.light) .hr-subtle {
 background: rgba(255, 255, 255, 0.08);
 }
}
.fitroute figure {
 margin: 0;
}
.fitroute-chips {
 display: flex;
 gap: 0.5em;
 margin-top: 0.5em;
}
.fitroute-chip {
 flex: 1;
 display: flex;
 flex-direction: column;
 align-items: center;
 justify-content: center;
 padding: 0.6em 0.5em;
 border: 1px solid #d0d0d0;
 border-radius: 4px;
 background-color: #f3f4f6;
 box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
}
.fitroute-label {
 font-size: 0.75em;
 color: #888;
 text-transform: uppercase;
 letter-spacing: 0.05em;
}
.fitroute-value {
 font-size: 1.1em;
 font-weight: 600;
 color: #242424;
}
@media (prefers-color-scheme: dark) {
 html:not(.dark):not(.light) .fitroute-chip {
 background-color: #1a1a1a;
 border-color: #333;
 box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
 }
 html:not(.dark):not(.light) .fitroute-label { color: #777; }
 html:not(.dark):not(.light) .fitroute-value { color: #dadada; }
}
html.dark .fitroute-chip {
 background-color: #1a1a1a;
 border-color: #333;
 box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
}
html.dark .fitroute-label { color: #777; }
html.dark .fitroute-value { color: #dadada; }
&lt;/style&gt;

&lt;p&gt;Spent the weekend at &lt;a href="https://en.wikipedia.org/wiki/Blegny"&gt;Blegny&lt;/a&gt; for the 27th Maasmarathon in &lt;a href="https://en.wikipedia.org/wiki/Vis%C3%A9"&gt;Visé&lt;/a&gt;. Took the opportunity to walk over the recently opened &lt;em&gt;&lt;a href="https://nl.wikipedia.org/wiki/Passerelle_van_Caestert"&gt;passerelle de Caster&lt;/a&gt;&lt;/em&gt; near &lt;a href="https://en.wikipedia.org/wiki/Kanne"&gt;Kanne&lt;/a&gt;, a suspension bridge at 55 metres height over the Albert Canal.&lt;/p&gt;
&lt;p&gt;Took the 15-minute trip from Visé to Maastricht in the Netherlands with the &lt;a href="https://nl.wikipedia.org/wiki/Drielandentrein"&gt;Drielandentrein&lt;/a&gt;. Visited a &lt;a href="https://www.visitmaastricht.com/en/locaties/30386516/boekhandel-dominicanen"&gt;bookshop in a church&lt;/a&gt;, went to the &lt;em&gt;&amp;ldquo;Porous Grounds, Sacred Codes&amp;rdquo;&lt;/em&gt; exhibition at &lt;a href="https://www.visitmaastricht.com/en/locations/4083627566/marres-1"&gt;Marres, House for Contemporary Culture&lt;/a&gt;, and stood at the &lt;a href="https://nl.wikipedia.org/wiki/Drielandenpunt_(Vaals)"&gt;Drielandenpunt&lt;/a&gt; in Vaals where the borders of Belgium, the Netherlands, and Germany intersect.&lt;/p&gt;
&lt;p&gt;For the marathon itself, I finally managed to run one under four hours. Couldn&amp;rsquo;t have done it without the pacer! My previous chip times were:&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Race&lt;/th&gt;
					&lt;th&gt;Year&lt;/th&gt;
					&lt;th&gt;Chip time&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Stockholm Marathon&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;2024&lt;/td&gt;
					&lt;td&gt;05:12:03&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;In Flanders Fields Marathon&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;2024&lt;/td&gt;
					&lt;td&gt;04:11:00&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;European Running Championships&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;2025&lt;/td&gt;
					&lt;td&gt;04:12:47&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;I&amp;rsquo;ll limit myself to one marathon per year. My next marathon would be the &lt;a href="https://www.erch2027.com/"&gt;European Running Championships 2027&lt;/a&gt; in Belgrade.&lt;/p&gt;</description></item><item><title>Anagram hikes</title><link>http://patrick.vanderspie.gl/notes/2026-03-21/</link><pubDate>Sat, 21 Mar 2026 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/notes/2026-03-21/</guid><description>&lt;p&gt;&lt;figure class="light"&gt;&lt;img src="http://patrick.vanderspie.gl/notes/20260321-anagram-hikes.gif"
			alt="Anagram Hikes"&gt;
&lt;/figure&gt;

&lt;figure class="dark"&gt;&lt;img src="http://patrick.vanderspie.gl/notes/20260321-anagram-hikes-dark.gif"
			alt="Anagram Hikes"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;bpost&lt;/em&gt; has a &lt;a href="https://www.bpost.be/nl/postcodevalidatie-tool"&gt;postal code validation tool&lt;/a&gt;, providing a spreadsheet of postal codes with names of Belgian communes and their &lt;a href="https://en.wikipedia.org/wiki/Deelgemeente"&gt;&lt;em&gt;deelgemeenten&lt;/em&gt;&lt;/a&gt;. We can convert the spreadsheet to a &lt;code&gt;CSV&lt;/code&gt; file using &lt;code&gt;ssconvert&lt;/code&gt;, and filter out all special postal codes&lt;label for="sidenote-2" class="sidenote-number"&gt;&lt;/label&gt;&lt;input type="checkbox" id="sidenote-2" class="sidenote-toggle"&gt;&lt;span class="sidenote"&gt;&lt;a href="https://en.wikipedia.org/wiki/Sinterklaas"&gt;Sinterklaas&lt;/a&gt; has his own postal code: 612, for 6th of December.&lt;/span&gt; (which are not linked to a commune, but to large public institutions and broadcasters that get their own postal code&lt;label for="sidenote-3" class="sidenote-number"&gt;&lt;/label&gt;&lt;input type="checkbox" id="sidenote-3" class="sidenote-toggle"&gt;&lt;span class="sidenote"&gt;&lt;a href="https://en.wikipedia.org/wiki/Postal_codes_in_Belgium"&gt;&lt;strong&gt;Postal codes in Belgium&lt;/strong&gt; &amp;ndash; &lt;em&gt;Wikipedia&lt;/em&gt;&lt;/a&gt;&lt;/span&gt;) with &lt;code&gt;xan&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ssconvert zipcodes_num_nl_2025.xls postal.csv
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;xan head postal.csv | xan view
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;Displaying 5 cols from 10 rows of &amp;lt;stdin&amp;gt;
┌───┬──────────┬────────────────┬──────────────┬────────────────┬───────────┐
│ - │ Postcode │ Plaatsnaam │ Deelgemeente │ Hoofdgemeente │ Provincie │
├───┼──────────┼────────────────┼──────────────┼────────────────┼───────────┤
│ 0 │ 612 │ Sinterklaas │ &amp;lt;empty&amp;gt; │ Sinterklaas │ &amp;lt;empty&amp;gt; │
│ 1 │ 1000 │ Brussel │ Neen │ BRUSSEL │ BRUSSEL │
│ 2 │ 1005 │ Verenigde Ver… │ &amp;lt;empty&amp;gt; │ Verenigde Ver… │ &amp;lt;empty&amp;gt; │
│ 3 │ 1006 │ Raad van de V… │ &amp;lt;empty&amp;gt; │ Raad van de V… │ &amp;lt;empty&amp;gt; │
│ 4 │ 1007 │ Assemblée de … │ &amp;lt;empty&amp;gt; │ Assemblée de … │ &amp;lt;empty&amp;gt; │
│ 5 │ 1008 │ Kamer van Vol… │ &amp;lt;empty&amp;gt; │ Kamer van Vol… │ &amp;lt;empty&amp;gt; │
│ 6 │ 1009 │ Belgische Sen… │ &amp;lt;empty&amp;gt; │ Belgische Sen… │ &amp;lt;empty&amp;gt; │
│ 7 │ 1011 │ Vlaams Parlem… │ &amp;lt;empty&amp;gt; │ Vlaams Parlem… │ &amp;lt;empty&amp;gt; │
│ 8 │ 1012 │ Parlement de … │ &amp;lt;empty&amp;gt; │ Parlement de … │ &amp;lt;empty&amp;gt; │
│ 9 │ 1020 │ Laken │ Ja │ BRUSSEL │ BRUSSEL │
└───┴──────────┴────────────────┴──────────────┴────────────────┴───────────┘
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Filtering out these special cases:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Displaying 5 cols from 10 rows of &amp;lt;stdin&amp;gt;
┌───┬──────────┬─────────────────────┬───────────┬─────────────────────┬───────────┐
│ - │ Postcode │ Plaatsnaam │ Deelgeme… │ Hoofdgemeente │ Provincie │
├───┼──────────┼─────────────────────┼───────────┼─────────────────────┼───────────┤
│ 0 │ 1000 │ Brussel │ Neen │ BRUSSEL │ BRUSSEL │
│ 1 │ 1020 │ Laken │ Ja │ BRUSSEL │ BRUSSEL │
│ 2 │ 1030 │ Schaarbeek │ Neen │ SCHAARBEEK │ BRUSSEL │
│ 3 │ 1040 │ Etterbeek │ Neen │ ETTERBEEK │ BRUSSEL │
│ 4 │ 1050 │ Elsene │ Neen │ ELSENE │ BRUSSEL │
│ 5 │ 1060 │ Sint-Gillis │ Neen │ SINT-GILLIS │ BRUSSEL │
│ 6 │ 1070 │ Anderlecht │ Neen │ ANDERLECHT │ BRUSSEL │
│ 7 │ 1080 │ Sint-Jans-Molenbeek │ Neen │ SINT-JANS-MOLENBEEK │ BRUSSEL │
│ 8 │ 1081 │ Koekelberg │ Neen │ KOEKELBERG │ BRUSSEL │
│ 9 │ 1082 │ Sint-Agatha-Berchem │ Neen │ SINT-AGATHA-BERCHEM │ BRUSSEL │
└───┴──────────┴─────────────────────┴───────────┴─────────────────────┴───────────┘
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We are interested in both the names of &lt;em&gt;hoofdgemeenten&lt;/em&gt; and &lt;em&gt;deelgemeenten&lt;/em&gt; in lowercase. We put both of these in one column using &lt;code&gt;xan unpivot 1,3&lt;/code&gt;, which puts all values in a column named &lt;code&gt;value&lt;/code&gt;. We now have some duplicates in this column, which is why we also need &lt;code&gt;dedup&lt;/code&gt; before writing these to a &lt;code&gt;towns.txt&lt;/code&gt; file.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;xan filter &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;!eq(Deelgemeente, &amp;#39;&amp;#39;)&amp;#34;&lt;/span&gt; postal.csv &lt;span style="color:#666;font-style:italic"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	| xan transform 1,3 &lt;span style="color:#666;font-style:italic"&gt;&amp;#39;lower(_)&amp;#39;&lt;/span&gt; &lt;span style="color:#666;font-style:italic"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	| xan unpivot 1,3 &lt;span style="color:#666;font-style:italic"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	| xan &lt;span style="font-weight:bold;text-decoration:underline"&gt;select&lt;/span&gt; value &lt;span style="color:#666;font-style:italic"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	| xan dedup &amp;gt; towns.txt
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We end up with a list of 2733 names:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;xan head towns.txt | xan view
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;Displaying 1 col from 10 rows of &amp;lt;stdin&amp;gt;
┌───┬─────────────────────┐
│ - │ value │
├───┼─────────────────────┤
│ 0 │ brussel │
│ 1 │ laken │
│ 2 │ schaarbeek │
│ 3 │ etterbeek │
│ 4 │ elsene │
│ 5 │ sint-gillis │
│ 6 │ anderlecht │
│ 7 │ sint-jans-molenbeek │
│ 8 │ koekelberg │
│ 9 │ sint-agatha-berchem │
└───┴─────────────────────┘
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;With the &lt;a href="http://patrick.vanderspie.gl/posts/scrambled-stations/#single-word-anagrams"&gt;alphabetic map&lt;/a&gt; of these names, we get 18 anagram town pairs for which we plan hiking routes using the &lt;a href="https://openrouteservice.org"&gt;openrouteservice API&lt;/a&gt;.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;rosée ⟷ sorée
idegem ⟷ diegem
olen ⟷ olne
tiegem ⟷ itegem
seraing ⟷ ragnies
herent ⟷ herten
erpe ⟷ peer
laken ⟷ alken
meerbeke ⟷ meerbeek
mere ⟷ meer
mollem ⟷ lommel
herve ⟷ hever
virelles ⟷ serville
veulen ⟷ leuven
borsbeke ⟷ borsbeek
berloz ⟷ borlez
lembeke ⟷ lembeek
edingen ⟷ gedinne
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;figure class="light"&gt;&lt;img src="http://patrick.vanderspie.gl/notes/20260321-anagram-hikes.png"
			alt="Anagram Hikes"&gt;
&lt;/figure&gt;

&lt;figure class="dark"&gt;&lt;img src="http://patrick.vanderspie.gl/notes/20260321-anagram-hikes-dark.png"
			alt="Anagram Hikes"&gt;
&lt;/figure&gt;
&lt;/p&gt;</description></item><item><title>Your work is not just content</title><link>http://patrick.vanderspie.gl/posts/content/</link><pubDate>Fri, 06 Feb 2026 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/posts/content/</guid><description>&lt;div class="quote-block"&gt;
 &lt;blockquote class="quote-content"&gt;Social media platforms provide value to independent creatives by allowing them to fully focus on creating instead of having to figure out how to share their work. Sadly, however, these same platforms reduce creative artists to content creators. When we label artwork — be it short- or long-form writing, illustration, photography, music, or video — as content, we turn unique works into interchangeable slop for consumption by users. I believe that the corporate web&amp;rsquo;s focus on user engagement plays a large role in this degradation, and that the independent web might offer a solution.&lt;/blockquote&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Keep reading at &lt;em&gt;&lt;strong&gt;&lt;a href="https://goodinternetmagazine.com/your-work-is-not-just-content/"&gt;Good Internet&lt;/a&gt;&lt;/strong&gt;&lt;/em&gt;!&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Visualising Order in Sequences</title><link>http://patrick.vanderspie.gl/posts/nested-words/</link><pubDate>Tue, 13 Jan 2026 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/posts/nested-words/</guid><description>&lt;h2 id="sequences"&gt;Sequences&lt;/h2&gt;
&lt;h3 id="linear-order"&gt;Linear Order&lt;/h3&gt;
&lt;p&gt;In a sequence, each element directly follows at most one element and precedes at most one other, forming a linear chain. We can visualise this through nodes of &lt;a href="https://en.wikipedia.org/wiki/Directed_graph"&gt;directed graphs&lt;/a&gt; that are connected using directed edges that represent the linear order between consecutive elements.&lt;/p&gt;
&lt;p&gt;The English word &amp;ldquo;&lt;code&gt;sequence&lt;/code&gt;&amp;rdquo; (which is an ordered sequence of the eight consecutive elements &lt;code&gt;s&lt;/code&gt;, &lt;code&gt;e&lt;/code&gt;, &lt;code&gt;q&lt;/code&gt;, &lt;code&gt;u&lt;/code&gt;, &lt;code&gt;e&lt;/code&gt;, &lt;code&gt;n&lt;/code&gt;, &lt;code&gt;c&lt;/code&gt;, &lt;code&gt;e&lt;/code&gt;), for example, can be visualised using a directed graph:&lt;/p&gt;

&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/nw-sequence.svg" class="invert-dark" loading="lazy" /&gt;


&lt;p&gt;Full sentences can also be seen as sequences of ordered symbols. As an example, we have the sentence &amp;ldquo;&lt;code&gt;This is a visualisation of linear order&lt;/code&gt;&amp;rdquo;. Spaces are also considered elements of the sequence, but we slightly reduce the opacity of their nodes for readability:&lt;/p&gt;

&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/nw-sentence.svg" class="invert-dark" loading="lazy" /&gt;


&lt;p&gt;We can drop the node labels to visualise the same sentence as:&lt;/p&gt;

&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/nw-large-sequence.svg" class="invert-dark" loading="lazy" /&gt;


&lt;p&gt;Order in sequences matters, and these sequences are not restricted to written language. Other examples include sequences of actions (&lt;em&gt;e.g., the sequence of actions that you perform to pour yourself a cup of coffee, as you can&amp;rsquo;t brew coffee before turning on the machine&lt;/em&gt;) or music (&lt;em&gt;e.g., the consecutive notes that make up a specific melody, as swapping the notes around gives us another melody&lt;/em&gt;).&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="hierarchically-nested-matchings"&gt;Hierarchically Nested Matchings&lt;/h3&gt;
&lt;p&gt;Many structures also have a natural hierarchical organisation (&lt;em&gt;e.g., we can group words into sentences, paragraphs, sections, and so on&lt;/em&gt;). For this reason, we also want a way to describe and visualise hierarchical structure.&lt;/p&gt;
&lt;p&gt;This is the visualisation of the linear order in the sequence &amp;ldquo;&lt;code&gt;nested word&lt;/code&gt;&amp;rdquo;:&lt;/p&gt;

&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/nw-nested-word.svg" class="invert-dark" loading="lazy" /&gt;


&lt;p&gt;We know that the sequence &amp;ldquo;&lt;code&gt;nested word&lt;/code&gt;&amp;rdquo; can naturally be split into two contiguous subsequences: &amp;ldquo;&lt;code&gt;nested&lt;/code&gt;&amp;rdquo; and &amp;ldquo;&lt;code&gt;word&lt;/code&gt;&amp;rdquo;. If we add symbols &amp;ldquo;&lt;code&gt;⟨&lt;/code&gt;&amp;rdquo; and &amp;ldquo;&lt;code&gt;⟩&lt;/code&gt;&amp;rdquo; that respectively denote the start and end of a word, we get the following:&lt;/p&gt;

&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/grouped-words.svg" class="invert-dark" loading="lazy" /&gt;


&lt;p&gt;We name the &amp;ldquo;start of a word&amp;rdquo; a &lt;strong&gt;call position&lt;/strong&gt; and &amp;ldquo;the end of that same word&amp;rdquo; its matching &lt;strong&gt;return position&lt;/strong&gt;. All other elements are &lt;strong&gt;internal positions&lt;/strong&gt;. These matches give rise to different &lt;strong&gt;nestings&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;We represent call and return positions using differently-coloured nodes, and represent matches using dashed directed edges from nodes representing call positions to nodes representing matching return positions:&lt;/p&gt;

&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/nw-grouped-words.svg" class="invert-dark" loading="lazy" /&gt;


&lt;h2 id="nested-words"&gt;Nested Words&lt;/h2&gt;
&lt;p&gt;More formally, a &lt;strong&gt;nested word&lt;/strong&gt;&lt;label for="sidenote-6" class="sidenote-number"&gt;&lt;/label&gt;&lt;input type="checkbox" id="sidenote-6" class="sidenote-toggle"&gt;&lt;span class="sidenote"&gt;&lt;a href="https://www.cis.upenn.edu/~alur/nw.html"&gt;Nested Words - Rajeev Alur&lt;/a&gt;&lt;/span&gt; is a sequence of elements $w = s_{1} \ldots s_{\ell}$ together with a &lt;strong&gt;matching relation&lt;/strong&gt;, which is a set of matches $i \rightsquigarrow j$ that connect call positions $i$ to their return positions $j$.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;For all matches $i \rightsquigarrow j$:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Nestings only go forward:&lt;/strong&gt; $i &amp;lt; j$&lt;/li&gt;
&lt;/ul&gt;

&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/forward.svg" class="invert-dark" loading="lazy" /&gt;


&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No two nestings share positions:&lt;/strong&gt; $|\{ i \mid i \rightsquigarrow j \}| \leq 1$ and $|\{ j \mid i \rightsquigarrow j \}| \leq 1$&lt;/li&gt;
&lt;/ul&gt;

&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/sharing.svg" class="invert-dark" loading="lazy" /&gt;


&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No two nestings cross:&lt;/strong&gt; if $i \rightsquigarrow j$ and $i&amp;rsquo; \rightsquigarrow j&amp;rsquo;$, we cannot have $i &amp;lt; i&amp;rsquo; &amp;lt; j &amp;lt; j'$&lt;/li&gt;
&lt;/ul&gt;

&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/crossing.svg" class="invert-dark" loading="lazy" /&gt;


&lt;h3 id="visualising-nestings"&gt;Visualising Nestings&lt;/h3&gt;
&lt;p&gt;If we visualise &amp;ldquo;&lt;code&gt;this is a visualisation of linear order&lt;/code&gt;&amp;rdquo;, we get:&lt;/p&gt;

&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/nw-words.svg" class="invert-dark" loading="lazy" /&gt;


&lt;p&gt;Trying out different &lt;a href="https://graphviz.org/docs/layouts/"&gt;graph layouts&lt;/a&gt;, we get:&lt;/p&gt;

&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/nw-new-layout.svg" class="invert-dark" loading="lazy" /&gt;


&lt;p&gt;Visualising the palindromic phrase&lt;label for="sidenote-12" class="sidenote-number"&gt;&lt;/label&gt;&lt;input type="checkbox" id="sidenote-12" class="sidenote-toggle"&gt;&lt;span class="sidenote"&gt;&lt;a href="https://en.wikipedia.org/wiki/List_of_English_palindromic_phrases"&gt;List of English palindromic phrases - Wikipedia&lt;/a&gt;&lt;/span&gt; &amp;ldquo;&lt;code&gt;⟨⟨⟨Lived⟩ ⟨on⟩ ⟨decaf⟩;⟩ ⟨⟨faced⟩ ⟨no⟩ ⟨devil⟩.⟩⟩&lt;/code&gt;&amp;rdquo;, for example, gives us some nice symmetries (as we have two groups, each with three words, that each respectively have five, two, and five elements):&lt;/p&gt;

&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/nw-decaf.svg" class="invert-dark" loading="lazy" /&gt;


&lt;hr&gt;
&lt;h2 id="nested-substitution-rules"&gt;Nested Substitution Rules&lt;/h2&gt;
&lt;p&gt;Reading through Stephen Wolfram&amp;rsquo;s &lt;a href="https://writings.stephenwolfram.com/2026/01/what-is-ruliology/"&gt;ruliology&lt;/a&gt;, I wondered what kind of nested structures we could obtain using simple substitution rules (like repeatedly changing internal positions labelled &lt;code&gt;a&lt;/code&gt; with a nesting &lt;code&gt;⟨aaa⟩&lt;/code&gt;).&lt;/p&gt;
&lt;h3 id="example-1"&gt;Example #1&lt;/h3&gt;
&lt;h4 id="initial-condition"&gt;Initial Condition&lt;/h4&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;a
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="replacement-rule"&gt;Replacement Rule&lt;/h4&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;a → ⟨aaa⟩
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="looping-visualisation-6-steps"&gt;Looping Visualisation (6 steps)&lt;/h4&gt;
&lt;div class="svg-sequence-container" id="svg-seq-posts-nested-words-animation-1"&gt;&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/animation-1/animation-step-000.svg" alt="Animated nested word visualisation" class="svg-sequence-frame invert-dark active" loading="lazy" /&gt;&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/animation-1/animation-step-001.svg" alt="Animated nested word visualisation" class="svg-sequence-frame invert-dark" loading="lazy" /&gt;&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/animation-1/animation-step-002.svg" alt="Animated nested word visualisation" class="svg-sequence-frame invert-dark" loading="lazy" /&gt;&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/animation-1/animation-step-003.svg" alt="Animated nested word visualisation" class="svg-sequence-frame invert-dark" loading="lazy" /&gt;&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/animation-1/animation-step-004.svg" alt="Animated nested word visualisation" class="svg-sequence-frame invert-dark" loading="lazy" /&gt;&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/animation-1/animation-step-005.svg" alt="Animated nested word visualisation" class="svg-sequence-frame invert-dark" loading="lazy" /&gt;&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/animation-1/animation-step-000.svg" alt="" class="svg-sequence-afterimage invert-dark" loading="lazy" aria-hidden="true" /&gt;&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/animation-1/animation-step-001.svg" alt="" class="svg-sequence-afterimage invert-dark" loading="lazy" aria-hidden="true" /&gt;&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/animation-1/animation-step-002.svg" alt="" class="svg-sequence-afterimage invert-dark" loading="lazy" aria-hidden="true" /&gt;&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/animation-1/animation-step-003.svg" alt="" class="svg-sequence-afterimage invert-dark" loading="lazy" aria-hidden="true" /&gt;&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/animation-1/animation-step-004.svg" alt="" class="svg-sequence-afterimage invert-dark" loading="lazy" aria-hidden="true" /&gt;&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/animation-1/animation-step-005.svg" alt="" class="svg-sequence-afterimage invert-dark" loading="lazy" aria-hidden="true" /&gt;&lt;/div&gt;
&lt;style&gt;
#svg-seq-posts-nested-words-animation-1 {
 position: relative;
 display: inline-block;
}
#svg-seq-posts-nested-words-animation-1 .svg-sequence-frame,
#svg-seq-posts-nested-words-animation-1 .svg-sequence-afterimage {
 position: absolute;
 top: 0;
 left: 0;
 opacity: 0;
}
#svg-seq-posts-nested-words-animation-1 .svg-sequence-frame {
 animation: 6s steps(1) infinite;
 z-index: 2;
}
#svg-seq-posts-nested-words-animation-1 .svg-sequence-afterimage {
 animation: 6s steps(1) infinite;
 z-index: 1;
}
#svg-seq-posts-nested-words-animation-1 .svg-sequence-frame:first-child {
 position: relative;
}#svg-seq-posts-nested-words-animation-1 .svg-sequence-frame:nth-child(1) {
 animation-name: svg-frame-svg-seq-posts-nested-words-animation-1-0;
}
@keyframes svg-frame-svg-seq-posts-nested-words-animation-1-0 {
 0%, 0% { opacity: 0; }
 0%, 8.333333333333334% { opacity: 1; }
 8.333333333333334%, 91.66666666666667% { opacity: 0; }
 91.66666666666667%, 100% { opacity: 1; }
 100%, 100% { opacity: 0; }
}#svg-seq-posts-nested-words-animation-1 .svg-sequence-frame:nth-child(2) {
 animation-name: svg-frame-svg-seq-posts-nested-words-animation-1-1;
}
@keyframes svg-frame-svg-seq-posts-nested-words-animation-1-1 {
 0%, 8.333333333333334% { opacity: 0; }
 8.333333333333334%, 16.666666666666668% { opacity: 1; }
 16.666666666666668%, 83.33333333333334% { opacity: 0; }
 83.33333333333334%, 91.66666666666667% { opacity: 1; }
 91.66666666666667%, 100% { opacity: 0; }
}#svg-seq-posts-nested-words-animation-1 .svg-sequence-frame:nth-child(3) {
 animation-name: svg-frame-svg-seq-posts-nested-words-animation-1-2;
}
@keyframes svg-frame-svg-seq-posts-nested-words-animation-1-2 {
 0%, 16.666666666666668% { opacity: 0; }
 16.666666666666668%, 25% { opacity: 1; }
 25%, 75% { opacity: 0; }
 75%, 83.33333333333334% { opacity: 1; }
 83.33333333333334%, 100% { opacity: 0; }
}#svg-seq-posts-nested-words-animation-1 .svg-sequence-frame:nth-child(4) {
 animation-name: svg-frame-svg-seq-posts-nested-words-animation-1-3;
}
@keyframes svg-frame-svg-seq-posts-nested-words-animation-1-3 {
 0%, 25% { opacity: 0; }
 25%, 33.333333333333336% { opacity: 1; }
 33.333333333333336%, 66.66666666666667% { opacity: 0; }
 66.66666666666667%, 75% { opacity: 1; }
 75%, 100% { opacity: 0; }
}#svg-seq-posts-nested-words-animation-1 .svg-sequence-frame:nth-child(5) {
 animation-name: svg-frame-svg-seq-posts-nested-words-animation-1-4;
}
@keyframes svg-frame-svg-seq-posts-nested-words-animation-1-4 {
 0%, 33.333333333333336% { opacity: 0; }
 33.333333333333336%, 41.66666666666667% { opacity: 1; }
 41.66666666666667%, 58.333333333333336% { opacity: 0; }
 58.333333333333336%, 66.66666666666667% { opacity: 1; }
 66.66666666666667%, 100% { opacity: 0; }
}#svg-seq-posts-nested-words-animation-1 .svg-sequence-frame:nth-child(6) {
 animation-name: svg-frame-svg-seq-posts-nested-words-animation-1-5;
}
@keyframes svg-frame-svg-seq-posts-nested-words-animation-1-5 {
 0%, 41.66666666666667% { opacity: 0; }
 41.66666666666667%, 50% { opacity: 1; }
 50%, 50% { opacity: 0; }
 50%, 58.333333333333336% { opacity: 1; }
 58.333333333333336%, 100% { opacity: 0; }
}#svg-seq-posts-nested-words-animation-1 .svg-sequence-afterimage:nth-child(7) {
 animation-name: svg-afterimage-svg-seq-posts-nested-words-animation-1-0;
}
@keyframes svg-afterimage-svg-seq-posts-nested-words-animation-1-0 {
 0%, 8.333333333333334% { opacity: 0; }
 8.333333333333334%, 16.666666666666668% { opacity: 0.1; }
 16.666666666666668%, 83.33333333333334% { opacity: 0; }
 83.33333333333334%, 91.66666666666667% { opacity: 0.1; }
 91.66666666666667%, 100% { opacity: 0; }
}#svg-seq-posts-nested-words-animation-1 .svg-sequence-afterimage:nth-child(8) {
 animation-name: svg-afterimage-svg-seq-posts-nested-words-animation-1-1;
}
@keyframes svg-afterimage-svg-seq-posts-nested-words-animation-1-1 {
 0%, 16.666666666666668% { opacity: 0; }
 16.666666666666668%, 25% { opacity: 0.1; }
 25%, 75% { opacity: 0; }
 75%, 83.33333333333334% { opacity: 0.1; }
 83.33333333333334%, 100% { opacity: 0; }
}#svg-seq-posts-nested-words-animation-1 .svg-sequence-afterimage:nth-child(9) {
 animation-name: svg-afterimage-svg-seq-posts-nested-words-animation-1-2;
}
@keyframes svg-afterimage-svg-seq-posts-nested-words-animation-1-2 {
 0%, 25% { opacity: 0; }
 25%, 33.333333333333336% { opacity: 0.1; }
 33.333333333333336%, 66.66666666666667% { opacity: 0; }
 66.66666666666667%, 75% { opacity: 0.1; }
 75%, 100% { opacity: 0; }
}#svg-seq-posts-nested-words-animation-1 .svg-sequence-afterimage:nth-child(10) {
 animation-name: svg-afterimage-svg-seq-posts-nested-words-animation-1-3;
}
@keyframes svg-afterimage-svg-seq-posts-nested-words-animation-1-3 {
 0%, 33.333333333333336% { opacity: 0; }
 33.333333333333336%, 41.66666666666667% { opacity: 0.1; }
 41.66666666666667%, 58.333333333333336% { opacity: 0; }
 58.333333333333336%, 66.66666666666667% { opacity: 0.1; }
 66.66666666666667%, 100% { opacity: 0; }
}#svg-seq-posts-nested-words-animation-1 .svg-sequence-afterimage:nth-child(11) {
 animation-name: svg-afterimage-svg-seq-posts-nested-words-animation-1-4;
}
@keyframes svg-afterimage-svg-seq-posts-nested-words-animation-1-4 {
 0%, 41.66666666666667% { opacity: 0; }
 41.66666666666667%, 50% { opacity: 0.1; }
 50%, 50% { opacity: 0; }
 50%, 58.333333333333336% { opacity: 0.1; }
 58.333333333333336%, 100% { opacity: 0; }
}#svg-seq-posts-nested-words-animation-1 .svg-sequence-afterimage:nth-child(12) {
 animation-name: svg-afterimage-svg-seq-posts-nested-words-animation-1-5;
}
@keyframes svg-afterimage-svg-seq-posts-nested-words-animation-1-5 {
 0%, 50% { opacity: 0; }
 50%, 58.333333333333336% { opacity: 0.1; }
 58.333333333333336%, 41.66666666666667% { opacity: 0; }
 41.66666666666667%, 50% { opacity: 0.1; }
 50%, 100% { opacity: 0; }
}&lt;/style&gt;
&lt;hr&gt;
&lt;h3 id="example-2"&gt;Example #2&lt;/h3&gt;
&lt;h4 id="initial-condition-1"&gt;Initial Condition&lt;/h4&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;ab
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="replacement-rule-1"&gt;Replacement Rule&lt;/h4&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;a → bb
b → ⟨aa⟩
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="looping-visualisation-9-steps"&gt;Looping Visualisation (9 steps)&lt;/h4&gt;
&lt;div class="svg-sequence-container" id="svg-seq-posts-nested-words-animation-2"&gt;&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/animation-2/animation-step-000.svg" alt="Animated nested word visualisation" class="svg-sequence-frame invert-dark active" loading="lazy" /&gt;&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/animation-2/animation-step-001.svg" alt="Animated nested word visualisation" class="svg-sequence-frame invert-dark" loading="lazy" /&gt;&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/animation-2/animation-step-002.svg" alt="Animated nested word visualisation" class="svg-sequence-frame invert-dark" loading="lazy" /&gt;&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/animation-2/animation-step-003.svg" alt="Animated nested word visualisation" class="svg-sequence-frame invert-dark" loading="lazy" /&gt;&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/animation-2/animation-step-004.svg" alt="Animated nested word visualisation" class="svg-sequence-frame invert-dark" loading="lazy" /&gt;&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/animation-2/animation-step-005.svg" alt="Animated nested word visualisation" class="svg-sequence-frame invert-dark" loading="lazy" /&gt;&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/animation-2/animation-step-006.svg" alt="Animated nested word visualisation" class="svg-sequence-frame invert-dark" loading="lazy" /&gt;&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/animation-2/animation-step-007.svg" alt="Animated nested word visualisation" class="svg-sequence-frame invert-dark" loading="lazy" /&gt;&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/animation-2/animation-step-008.svg" alt="Animated nested word visualisation" class="svg-sequence-frame invert-dark" loading="lazy" /&gt;&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/animation-2/animation-step-000.svg" alt="" class="svg-sequence-afterimage invert-dark" loading="lazy" aria-hidden="true" /&gt;&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/animation-2/animation-step-001.svg" alt="" class="svg-sequence-afterimage invert-dark" loading="lazy" aria-hidden="true" /&gt;&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/animation-2/animation-step-002.svg" alt="" class="svg-sequence-afterimage invert-dark" loading="lazy" aria-hidden="true" /&gt;&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/animation-2/animation-step-003.svg" alt="" class="svg-sequence-afterimage invert-dark" loading="lazy" aria-hidden="true" /&gt;&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/animation-2/animation-step-004.svg" alt="" class="svg-sequence-afterimage invert-dark" loading="lazy" aria-hidden="true" /&gt;&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/animation-2/animation-step-005.svg" alt="" class="svg-sequence-afterimage invert-dark" loading="lazy" aria-hidden="true" /&gt;&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/animation-2/animation-step-006.svg" alt="" class="svg-sequence-afterimage invert-dark" loading="lazy" aria-hidden="true" /&gt;&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/animation-2/animation-step-007.svg" alt="" class="svg-sequence-afterimage invert-dark" loading="lazy" aria-hidden="true" /&gt;&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/animation-2/animation-step-008.svg" alt="" class="svg-sequence-afterimage invert-dark" loading="lazy" aria-hidden="true" /&gt;&lt;/div&gt;
&lt;style&gt;
#svg-seq-posts-nested-words-animation-2 {
 position: relative;
 display: inline-block;
}
#svg-seq-posts-nested-words-animation-2 .svg-sequence-frame,
#svg-seq-posts-nested-words-animation-2 .svg-sequence-afterimage {
 position: absolute;
 top: 0;
 left: 0;
 opacity: 0;
}
#svg-seq-posts-nested-words-animation-2 .svg-sequence-frame {
 animation: 5s steps(1) infinite;
 z-index: 2;
}
#svg-seq-posts-nested-words-animation-2 .svg-sequence-afterimage {
 animation: 5s steps(1) infinite;
 z-index: 1;
}
#svg-seq-posts-nested-words-animation-2 .svg-sequence-frame:first-child {
 position: relative;
}#svg-seq-posts-nested-words-animation-2 .svg-sequence-frame:nth-child(1) {
 animation-name: svg-frame-svg-seq-posts-nested-words-animation-2-0;
}
@keyframes svg-frame-svg-seq-posts-nested-words-animation-2-0 {
 0%, 0% { opacity: 0; }
 0%, 5.555555555555555% { opacity: 1; }
 5.555555555555555%, 94.44444444444444% { opacity: 0; }
 94.44444444444444%, 100% { opacity: 1; }
 100%, 100% { opacity: 0; }
}#svg-seq-posts-nested-words-animation-2 .svg-sequence-frame:nth-child(2) {
 animation-name: svg-frame-svg-seq-posts-nested-words-animation-2-1;
}
@keyframes svg-frame-svg-seq-posts-nested-words-animation-2-1 {
 0%, 5.555555555555555% { opacity: 0; }
 5.555555555555555%, 11.11111111111111% { opacity: 1; }
 11.11111111111111%, 88.88888888888889% { opacity: 0; }
 88.88888888888889%, 94.44444444444444% { opacity: 1; }
 94.44444444444444%, 100% { opacity: 0; }
}#svg-seq-posts-nested-words-animation-2 .svg-sequence-frame:nth-child(3) {
 animation-name: svg-frame-svg-seq-posts-nested-words-animation-2-2;
}
@keyframes svg-frame-svg-seq-posts-nested-words-animation-2-2 {
 0%, 11.11111111111111% { opacity: 0; }
 11.11111111111111%, 16.666666666666664% { opacity: 1; }
 16.666666666666664%, 83.33333333333333% { opacity: 0; }
 83.33333333333333%, 88.88888888888889% { opacity: 1; }
 88.88888888888889%, 100% { opacity: 0; }
}#svg-seq-posts-nested-words-animation-2 .svg-sequence-frame:nth-child(4) {
 animation-name: svg-frame-svg-seq-posts-nested-words-animation-2-3;
}
@keyframes svg-frame-svg-seq-posts-nested-words-animation-2-3 {
 0%, 16.666666666666664% { opacity: 0; }
 16.666666666666664%, 22.22222222222222% { opacity: 1; }
 22.22222222222222%, 77.77777777777777% { opacity: 0; }
 77.77777777777777%, 83.33333333333333% { opacity: 1; }
 83.33333333333333%, 100% { opacity: 0; }
}#svg-seq-posts-nested-words-animation-2 .svg-sequence-frame:nth-child(5) {
 animation-name: svg-frame-svg-seq-posts-nested-words-animation-2-4;
}
@keyframes svg-frame-svg-seq-posts-nested-words-animation-2-4 {
 0%, 22.22222222222222% { opacity: 0; }
 22.22222222222222%, 27.77777777777778% { opacity: 1; }
 27.77777777777778%, 72.22222222222221% { opacity: 0; }
 72.22222222222221%, 77.77777777777777% { opacity: 1; }
 77.77777777777777%, 100% { opacity: 0; }
}#svg-seq-posts-nested-words-animation-2 .svg-sequence-frame:nth-child(6) {
 animation-name: svg-frame-svg-seq-posts-nested-words-animation-2-5;
}
@keyframes svg-frame-svg-seq-posts-nested-words-animation-2-5 {
 0%, 27.77777777777778% { opacity: 0; }
 27.77777777777778%, 33.33333333333333% { opacity: 1; }
 33.33333333333333%, 66.66666666666666% { opacity: 0; }
 66.66666666666666%, 72.22222222222221% { opacity: 1; }
 72.22222222222221%, 100% { opacity: 0; }
}#svg-seq-posts-nested-words-animation-2 .svg-sequence-frame:nth-child(7) {
 animation-name: svg-frame-svg-seq-posts-nested-words-animation-2-6;
}
@keyframes svg-frame-svg-seq-posts-nested-words-animation-2-6 {
 0%, 33.33333333333333% { opacity: 0; }
 33.33333333333333%, 38.888888888888886% { opacity: 1; }
 38.888888888888886%, 61.11111111111111% { opacity: 0; }
 61.11111111111111%, 66.66666666666666% { opacity: 1; }
 66.66666666666666%, 100% { opacity: 0; }
}#svg-seq-posts-nested-words-animation-2 .svg-sequence-frame:nth-child(8) {
 animation-name: svg-frame-svg-seq-posts-nested-words-animation-2-7;
}
@keyframes svg-frame-svg-seq-posts-nested-words-animation-2-7 {
 0%, 38.888888888888886% { opacity: 0; }
 38.888888888888886%, 44.44444444444444% { opacity: 1; }
 44.44444444444444%, 55.55555555555556% { opacity: 0; }
 55.55555555555556%, 61.11111111111111% { opacity: 1; }
 61.11111111111111%, 100% { opacity: 0; }
}#svg-seq-posts-nested-words-animation-2 .svg-sequence-frame:nth-child(9) {
 animation-name: svg-frame-svg-seq-posts-nested-words-animation-2-8;
}
@keyframes svg-frame-svg-seq-posts-nested-words-animation-2-8 {
 0%, 44.44444444444444% { opacity: 0; }
 44.44444444444444%, 50% { opacity: 1; }
 50%, 50% { opacity: 0; }
 50%, 55.55555555555556% { opacity: 1; }
 55.55555555555556%, 100% { opacity: 0; }
}#svg-seq-posts-nested-words-animation-2 .svg-sequence-afterimage:nth-child(10) {
 animation-name: svg-afterimage-svg-seq-posts-nested-words-animation-2-0;
}
@keyframes svg-afterimage-svg-seq-posts-nested-words-animation-2-0 {
 0%, 5.555555555555555% { opacity: 0; }
 5.555555555555555%, 11.11111111111111% { opacity: 0.1; }
 11.11111111111111%, 88.88888888888889% { opacity: 0; }
 88.88888888888889%, 94.44444444444444% { opacity: 0.1; }
 94.44444444444444%, 100% { opacity: 0; }
}#svg-seq-posts-nested-words-animation-2 .svg-sequence-afterimage:nth-child(11) {
 animation-name: svg-afterimage-svg-seq-posts-nested-words-animation-2-1;
}
@keyframes svg-afterimage-svg-seq-posts-nested-words-animation-2-1 {
 0%, 11.11111111111111% { opacity: 0; }
 11.11111111111111%, 16.666666666666664% { opacity: 0.1; }
 16.666666666666664%, 83.33333333333333% { opacity: 0; }
 83.33333333333333%, 88.88888888888889% { opacity: 0.1; }
 88.88888888888889%, 100% { opacity: 0; }
}#svg-seq-posts-nested-words-animation-2 .svg-sequence-afterimage:nth-child(12) {
 animation-name: svg-afterimage-svg-seq-posts-nested-words-animation-2-2;
}
@keyframes svg-afterimage-svg-seq-posts-nested-words-animation-2-2 {
 0%, 16.666666666666664% { opacity: 0; }
 16.666666666666664%, 22.22222222222222% { opacity: 0.1; }
 22.22222222222222%, 77.77777777777777% { opacity: 0; }
 77.77777777777777%, 83.33333333333333% { opacity: 0.1; }
 83.33333333333333%, 100% { opacity: 0; }
}#svg-seq-posts-nested-words-animation-2 .svg-sequence-afterimage:nth-child(13) {
 animation-name: svg-afterimage-svg-seq-posts-nested-words-animation-2-3;
}
@keyframes svg-afterimage-svg-seq-posts-nested-words-animation-2-3 {
 0%, 22.22222222222222% { opacity: 0; }
 22.22222222222222%, 27.77777777777778% { opacity: 0.1; }
 27.77777777777778%, 72.22222222222221% { opacity: 0; }
 72.22222222222221%, 77.77777777777777% { opacity: 0.1; }
 77.77777777777777%, 100% { opacity: 0; }
}#svg-seq-posts-nested-words-animation-2 .svg-sequence-afterimage:nth-child(14) {
 animation-name: svg-afterimage-svg-seq-posts-nested-words-animation-2-4;
}
@keyframes svg-afterimage-svg-seq-posts-nested-words-animation-2-4 {
 0%, 27.77777777777778% { opacity: 0; }
 27.77777777777778%, 33.33333333333333% { opacity: 0.1; }
 33.33333333333333%, 66.66666666666666% { opacity: 0; }
 66.66666666666666%, 72.22222222222221% { opacity: 0.1; }
 72.22222222222221%, 100% { opacity: 0; }
}#svg-seq-posts-nested-words-animation-2 .svg-sequence-afterimage:nth-child(15) {
 animation-name: svg-afterimage-svg-seq-posts-nested-words-animation-2-5;
}
@keyframes svg-afterimage-svg-seq-posts-nested-words-animation-2-5 {
 0%, 33.33333333333333% { opacity: 0; }
 33.33333333333333%, 38.888888888888886% { opacity: 0.1; }
 38.888888888888886%, 61.11111111111111% { opacity: 0; }
 61.11111111111111%, 66.66666666666666% { opacity: 0.1; }
 66.66666666666666%, 100% { opacity: 0; }
}#svg-seq-posts-nested-words-animation-2 .svg-sequence-afterimage:nth-child(16) {
 animation-name: svg-afterimage-svg-seq-posts-nested-words-animation-2-6;
}
@keyframes svg-afterimage-svg-seq-posts-nested-words-animation-2-6 {
 0%, 38.888888888888886% { opacity: 0; }
 38.888888888888886%, 44.44444444444444% { opacity: 0.1; }
 44.44444444444444%, 55.55555555555556% { opacity: 0; }
 55.55555555555556%, 61.11111111111111% { opacity: 0.1; }
 61.11111111111111%, 100% { opacity: 0; }
}#svg-seq-posts-nested-words-animation-2 .svg-sequence-afterimage:nth-child(17) {
 animation-name: svg-afterimage-svg-seq-posts-nested-words-animation-2-7;
}
@keyframes svg-afterimage-svg-seq-posts-nested-words-animation-2-7 {
 0%, 44.44444444444444% { opacity: 0; }
 44.44444444444444%, 50% { opacity: 0.1; }
 50%, 50% { opacity: 0; }
 50%, 55.55555555555556% { opacity: 0.1; }
 55.55555555555556%, 100% { opacity: 0; }
}#svg-seq-posts-nested-words-animation-2 .svg-sequence-afterimage:nth-child(18) {
 animation-name: svg-afterimage-svg-seq-posts-nested-words-animation-2-8;
}
@keyframes svg-afterimage-svg-seq-posts-nested-words-animation-2-8 {
 0%, 50% { opacity: 0; }
 50%, 55.55555555555556% { opacity: 0.1; }
 55.55555555555556%, 44.44444444444444% { opacity: 0; }
 44.44444444444444%, 50% { opacity: 0.1; }
 50%, 100% { opacity: 0; }
}&lt;/style&gt;
&lt;hr&gt;
&lt;h2 id="visualising-this-post"&gt;Visualising this post&lt;/h2&gt;
&lt;p&gt;Finally, we can apply nested word visualisation to this post itself by treating the post&amp;rsquo;s structure as a nested word:&lt;/p&gt;

&lt;img src="http://patrick.vanderspie.gl/posts/nested-words/nw-post.svg" class="invert-dark" loading="lazy" /&gt;

</description></item><item><title>&lt; 1000 kilometres in 2025</title><link>http://patrick.vanderspie.gl/notes/2026-01-07/</link><pubDate>Wed, 07 Jan 2026 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/notes/2026-01-07/</guid><description>
&lt;img src="http://patrick.vanderspie.gl/notes/24-25_distance-comparison.png" class="invert-dark" loading="lazy" /&gt;


&lt;p&gt;See &lt;a href="http://patrick.vanderspie.gl/notes/2025-01-04"&gt;2024&lt;/a&gt;; will post &lt;em&gt;&amp;quot;&amp;gt; 1000 kilometres in 2026&amp;quot;&lt;/em&gt; next year.&lt;/p&gt;</description></item><item><title>Scrambled Stations</title><link>http://patrick.vanderspie.gl/posts/scrambled-stations/</link><pubDate>Fri, 08 Aug 2025 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/posts/scrambled-stations/</guid><description>&lt;div class="alfphabet-display"&gt;
Scrambled Stations
&lt;/div&gt;
&lt;div class="custom-title-date"&gt;
 
 
 
 &lt;time datetime="2025-08-08T00:00:00&amp;#43;00:00"&gt;8 August 2025&lt;/time&gt;
 
&lt;/div&gt;
&lt;h2 id="gehusselde-stationsnaam-ns"&gt;Gehusselde stationsnaam (NS)&lt;/h2&gt;
&lt;p&gt;The Dutch NS railway operator has the &lt;a href="https://www.ns.nl/dagje-uit/ontspanning/puzzel.html"&gt;&lt;em&gt;&amp;ldquo;gehusselde stationsnaam&amp;rdquo;&lt;/em&gt;&lt;/a&gt; game on their on-board train information displays: a puzzle where you have to figure out the hidden train station through an anagram of that station&amp;rsquo;s name. These puzzles are also on their &lt;a href="https://www.instagram.com/ns_online/p/CwejiNRqAJ7/"&gt;Instagram page&lt;/a&gt;: the puzzle &lt;em&gt;&amp;ldquo;Los Pichor Pathir&amp;rdquo;&lt;/em&gt;, for example, matches the Schiphol Airport railway station when unscrambled. As I barely know any Dutch railway station names, I was curious if something similar was feasibile for Belgian railway stations using Flemish dialect words.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="retrieving-wordlists"&gt;Retrieving wordlists&lt;/h2&gt;
&lt;p&gt;We first retrieve two wordlists: a list of Belgian railway stations, and a wordlist of Flemish dialect words. Afterwards, we use these wordlists to figure out if there are any single- or multi-word anagrams of one wordlist inside the other.&lt;/p&gt;
&lt;h3 id="belgian-railway-stations"&gt;Belgian railway stations&lt;/h3&gt;
&lt;p&gt;There&amp;rsquo;s a &lt;a href="https://github.com/iRail/stations/"&gt;complete list of Belgian railway stations&lt;/a&gt; available on GitHub, maintained by &lt;a href="https://github.com/irail"&gt;iRail&lt;/a&gt;. We can &lt;code&gt;curl&lt;/code&gt; the &lt;code&gt;stations.csv&lt;/code&gt; file from that repository.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl --output railway_stations.csv \ 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;https://raw.githubusercontent.com/iRail/stations/refs/heads/master/stations.csv
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This list of railway stations also contains lots of non-Belgian (often Dutch, German, and French) stations, which I assume are included as they are reachable by train from Belgium. We can filter out these non-Belgian stations using the &lt;code&gt;country-code&lt;/code&gt; column.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ xan filter &lt;span style="color:#666;font-style:italic"&gt;&amp;#39;col(&amp;#34;country-code&amp;#34;) ne &amp;#34;be&amp;#34;&amp;#39;&lt;/span&gt; railway_stations.csv | &lt;span style="color:#666;font-style:italic"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; xan &lt;span style="font-weight:bold;text-decoration:underline"&gt;select&lt;/span&gt; &lt;span style="color:#666;font-style:italic"&gt;&amp;#39;name,country-code&amp;#39;&lt;/span&gt; | &lt;span style="color:#666;font-style:italic"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; xan view -l 5
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;┌───┬─────────────────────┬──────────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ - │ name │ country-code │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├───┼─────────────────────┼──────────────┤
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ 0 │ &lt;span style=""&gt;&amp;#39;&lt;/span&gt;s Hertogenbosch │ nl │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ 1 │ Aachen Hbf │ de │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ 2 │ Agde │ fr │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ 3 │ Aime-la-Plagne │ fr │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ 4 │ Aix-en-Provence TGV │ fr │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ … │ … │ … │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└───┴─────────────────────┴──────────────┘
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Belgian railway stations sometimes have both a Dutch and French name. These names are mostly similar (like &lt;em&gt;&amp;ldquo;Brussel-Centraal&amp;rdquo;&lt;/em&gt; in Dutch and &lt;em&gt;&amp;ldquo;Bruxelles-Central&amp;rdquo;&lt;/em&gt; in French), but sometimes completely different (like &lt;a href="https://nl.wikipedia.org/wiki/Diesdelle#Geschiedenis"&gt;&lt;em&gt;&amp;ldquo;Diesdelle&amp;rdquo;&lt;/em&gt; and &lt;em&gt;&amp;ldquo;Vivier d&amp;rsquo;Oie&amp;rdquo;&lt;/em&gt;&lt;/a&gt;). For railway stations in Brussels, these variants are separated by a slash in the &lt;code&gt;name&lt;/code&gt; column of our &lt;code&gt;CSV&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ xan filter &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&amp;#39;/&amp;#39; in col(&amp;#39;name&amp;#39;)&amp;#34;&lt;/span&gt; railway_stations.csv | &lt;span style="color:#666;font-style:italic"&gt;\ &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; xan &lt;span style="font-weight:bold;text-decoration:underline"&gt;select&lt;/span&gt; &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;name&amp;#34;&lt;/span&gt; | &lt;span style="color:#666;font-style:italic"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; xan view -l 5
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;┌───┬────────────────────────────────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ - │ name │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├───┼────────────────────────────────────┤
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ 0 │ Arcaden/Arcades │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ 1 │ Boondaal/Boondael │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ 2 │ Bosvoorde/Boitsfort │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ 3 │ Brussel-Centraal/Bruxelles-Central │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ 4 │ Brussel-Congres/Bruxelles-Congrès │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ … │ … │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└───┴────────────────────────────────────┘
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We filter out non-Belgian railway stations, select the names of the remaining stations, split these names on forward slashes so that we get both the Dutch and French name on separate lines where appropriate, and write these lines to a separate text file.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;xan filter &amp;#39;col(&amp;#34;country-code&amp;#34;) eq &amp;#34;be&amp;#34;&amp;#39; railway_stations.csv | \ 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;xan select name | \ 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tr &amp;#39;/&amp;#39; &amp;#39;\n&amp;#39; &amp;gt; railway_stations.txt
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="flemish-dialect-words"&gt;Flemish dialect words&lt;/h3&gt;
&lt;p&gt;As far as I can tell, the &lt;a href="https://www.vlaamswoordenboek.be/"&gt;&amp;ldquo;Flemish dictionary&amp;rdquo;&lt;/a&gt; does not provide a downloadable wordlist. They do, however, have a page per letter of the alphabet containing all words starting with that letter. Luckily, these letter pages follow the same structure and contain all words on a single page, so by looping through only 26 pages (one for each letter of the alphabet), we can extract all listed words using &lt;code&gt;grep&lt;/code&gt; and &lt;code&gt;sed&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;for&lt;/span&gt; letter in {a..z}; &lt;span style="font-weight:bold;text-decoration:underline"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; curl -s https://www.vlaamswoordenboek.be/definities/begintmet/&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$letter&lt;/span&gt; | &lt;span style="color:#666;font-style:italic"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; grep -o &lt;span style="color:#666;font-style:italic"&gt;&amp;#39;&amp;lt;a href=&amp;#34;/definities/term/[^&amp;#34;]*&amp;#34;&amp;gt;[^&amp;lt;]*&amp;lt;/a&amp;gt; &amp;lt;br /&amp;gt;&amp;#39;&lt;/span&gt; | &lt;span style="color:#666;font-style:italic"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sed &lt;span style="color:#666;font-style:italic"&gt;&amp;#39;s/&amp;lt;a href=&amp;#34;[^&amp;#34;]*&amp;#34;&amp;gt;\([^&amp;lt;]*\)&amp;lt;\/a&amp;gt; &amp;lt;br \/&amp;gt;/\1/&amp;#39;&lt;/span&gt; &amp;gt;&amp;gt; flemish_wordlist.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="finding-anagrams"&gt;Finding anagrams&lt;/h2&gt;
&lt;p&gt;We first look at how to find &lt;strong&gt;single-word anagrams&lt;/strong&gt;&amp;mdash;where single Flemish dialect words are anagrams of certain railway stations&amp;mdash;using &lt;em&gt;&amp;ldquo;alphabetic maps&amp;rdquo;&lt;/em&gt;. We pair sets of railway stations with their anagram set, for example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#39;Ternat&amp;#39;} = {&amp;#39;ratten&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#39;Drongen&amp;#39;} = {&amp;#39;gronden&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#39;Aalst&amp;#39;} = {&amp;#39;slaat&amp;#39;, &amp;#39;staal&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="alfphabet-display alfphabet-scale-medium"&gt;
Ratten 🐀
&lt;/div&gt;
&lt;p&gt;Afterwards, we look at possible ways of finding &lt;strong&gt;multi-word anagrams&lt;/strong&gt;&amp;mdash;where multiple words combine to make up an anagram. Some examples, of which &lt;em&gt;&amp;quot;&lt;a href="https://www.vlaamswoordenboek.be/definities/term/houten"&gt;houten&lt;/a&gt; &lt;a href="https://www.vlaamswoordenboek.be/definities/term/afritser"&gt;afritser&lt;/a&gt;&amp;quot;&lt;/em&gt; (&amp;ldquo;wooden playground slide&amp;rdquo;) is my favourite:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#39;Athus-Frontiere&amp;#39;} = {&amp;#39;houten&amp;#39;} + {&amp;#39;afritser&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#39;Mechelen-Nekkerspoel&amp;#39;} = {&amp;#39;schoempelen&amp;#39;} + {&amp;#39;krekelen&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#39;Dave-Saint-Martin&amp;#39;} = {&amp;#39;mandataris&amp;#39;} + {&amp;#39;in vet&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#39;Mortsel-Deurnesteenweg&amp;#39;} = {&amp;#39;lutter&amp;#39;} + {&amp;#39;messe&amp;#39;} + {&amp;#39;onderwegen&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="alfphabet-display alfphabet-scale-medium"&gt;
Houten Afritser 🛝
&lt;/div&gt;
&lt;h3 id="single-word-anagrams"&gt;Single-word anagrams&lt;/h3&gt;
&lt;p&gt;When alphabetically ordering all characters within words, two distinct words result in the same ordering only if they are anagrams of each other. In Python, for example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span style="font-weight:bold;font-style:italic"&gt;sorted&lt;/span&gt;(&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;undefinability&amp;#34;&lt;/span&gt;) == &lt;span style="font-weight:bold;font-style:italic"&gt;sorted&lt;/span&gt;(&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;unidentifiably&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Thus, to find anagrams of Belgian railway stations in Flemish dialect words, we build two &lt;em&gt;alphabetic maps&lt;/em&gt;: dictionaries that map ordered characters to a set of &amp;ldquo;intra-wordlist anagrams&amp;rdquo;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;from&lt;/span&gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;collections&lt;/span&gt; &lt;span style="font-weight:bold;text-decoration:underline"&gt;import&lt;/span&gt; defaultdict
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;def&lt;/span&gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;get_key&lt;/span&gt;(word):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="font-weight:bold;text-decoration:underline"&gt;return&lt;/span&gt; &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&amp;#34;&lt;/span&gt;.join(&lt;span style="font-weight:bold;font-style:italic"&gt;sorted&lt;/span&gt;(&lt;span style="font-weight:bold;font-style:italic"&gt;filter&lt;/span&gt;(&lt;span style="font-weight:bold;font-style:italic"&gt;str&lt;/span&gt;.isalpha, word.lower())))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;def&lt;/span&gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;group&lt;/span&gt;(words):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	groups = defaultdict(&lt;span style="font-weight:bold;font-style:italic"&gt;set&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="font-weight:bold;text-decoration:underline"&gt;for&lt;/span&gt; word &lt;span style="font-weight:bold"&gt;in&lt;/span&gt; words:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		groups[get_key(word)].add(word)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="font-weight:bold;text-decoration:underline"&gt;return&lt;/span&gt; groups
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;with&lt;/span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;open&lt;/span&gt;(&lt;span style="color:#666;font-style:italic"&gt;&amp;#39;railway_stations.txt&amp;#39;&lt;/span&gt;, &lt;span style="color:#666;font-style:italic"&gt;&amp;#39;r&amp;#39;&lt;/span&gt;) &lt;span style="font-weight:bold;text-decoration:underline"&gt;as&lt;/span&gt; f:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; stations = &lt;span style="font-weight:bold;font-style:italic"&gt;set&lt;/span&gt;(line.strip() &lt;span style="font-weight:bold;text-decoration:underline"&gt;for&lt;/span&gt; line &lt;span style="font-weight:bold"&gt;in&lt;/span&gt; f)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; grouped_stations = group(stations)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;with&lt;/span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;open&lt;/span&gt;(&lt;span style="color:#666;font-style:italic"&gt;&amp;#39;flemish_wordlist.txt&amp;#39;&lt;/span&gt;, &lt;span style="color:#666;font-style:italic"&gt;&amp;#39;r&amp;#39;&lt;/span&gt;) &lt;span style="font-weight:bold;text-decoration:underline"&gt;as&lt;/span&gt; f:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; wordlist = &lt;span style="font-weight:bold;font-style:italic"&gt;set&lt;/span&gt;(line.strip() &lt;span style="font-weight:bold;text-decoration:underline"&gt;for&lt;/span&gt; line &lt;span style="font-weight:bold"&gt;in&lt;/span&gt; f)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; grouped_wordlist = group(wordlist)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To obtain the keys of these maps, we turn all characters of the words lowercase and filter out non-alphabetic characters before sorting. We loop through the set of words from each wordlist and build two separate alphabetic maps. Using these alphabetic maps, we can look for anagrams within the wordlists themselves. It turns out, for example, that only two pairs of stations are anagrams of each other:&lt;/p&gt;
&lt;div class="alfphabet-display alfphabet-scale-small"&gt;
Mollem = Lommel
&lt;/div&gt;
&lt;div class="alfphabet-display alfphabet-scale-small"&gt;
Diegem = Idegem
&lt;/div&gt;
&lt;p&gt;To find the &amp;ldquo;inter-wordlist anagrams&amp;rdquo;&amp;mdash;which is what we were originally interested in&amp;mdash;we look at the intersection of the keys between alphabetic maps. Every common key corresponds to pairs of anagrams:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;for&lt;/span&gt; key &lt;span style="font-weight:bold"&gt;in&lt;/span&gt; (grouped_stations.keys() &amp;amp; grouped_wordlist.keys()):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	grouped_stations[key], grouped_wordlist[key]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This results in the following set of single-word anagrams. (As there&amp;rsquo;s a small overlap between our wordlists, we also get a couple of trivial anagrams in return.)&lt;/p&gt;

&lt;div class="details-wrapper"&gt;
 &lt;details id="details-6"&gt;
 &lt;summary class="details-summary"&gt;Details&lt;/summary&gt;
 &lt;div class="details-content"&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Jette&amp;#39;}, {&amp;#39;tetje&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Temse&amp;#39;}, {&amp;#39;smete&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Lierde&amp;#39;}, {&amp;#39;leider&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Leman&amp;#39;}, {&amp;#39;lamen&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Ternat&amp;#39;}, {&amp;#39;ratten&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Kijkuit&amp;#39;}, {&amp;#39;kijkuit&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Boom&amp;#39;}, {&amp;#39;boom&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Godinne&amp;#39;}, {&amp;#39;doening&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Bleret&amp;#39;}, {&amp;#39;bretel&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Muizen&amp;#39;}, {&amp;#39;muizen&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Asse&amp;#39;}, {&amp;#39;asse&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Landen&amp;#39;}, {&amp;#39;landen&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Weerde&amp;#39;}, {&amp;#39;weerde&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Mol&amp;#39;}, {&amp;#39;mol&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Geel&amp;#39;}, {&amp;#39;leeg&amp;#39;, &amp;#39;Geel&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Sint-Niklaas&amp;#39;}, {&amp;#39;Sint-Niklaas&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Drongen&amp;#39;}, {&amp;#39;gronden&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Welle&amp;#39;}, {&amp;#39;welle&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Ruisbroek&amp;#39;}, {&amp;#39;ruisbroek&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Zele&amp;#39;}, {&amp;#39;zeel&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Meiser&amp;#39;}, {&amp;#39;misere&amp;#39;, &amp;#39;remise&amp;#39;, &amp;#39;eremis&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Spa&amp;#39;}, {&amp;#39;SAP&amp;#39;, &amp;#39;pas&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Menen&amp;#39;}, {&amp;#39;menne&amp;#39;, &amp;#39;nemen&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Lens&amp;#39;}, {&amp;#39;snel&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Tielt&amp;#39;}, {&amp;#39;titel&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Eupen&amp;#39;}, {&amp;#39;peune&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Engis&amp;#39;}, {&amp;#39;signe&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Eichem&amp;#39;}, {&amp;#39;chemie&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Ekeren&amp;#39;}, {&amp;#39;ne keer&amp;#39;, &amp;#39;nekeer&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Niel&amp;#39;}, {&amp;#39;lein&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Manage&amp;#39;}, {&amp;#39;gemaan&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Ronet&amp;#39;}, {&amp;#39;tenor&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Lot&amp;#39;}, {&amp;#39;lot&amp;#39;, &amp;#39;tol&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Essen&amp;#39;}, {&amp;#39;se-n-se&amp;#39;, &amp;#39;sense&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Lobbes&amp;#39;}, {&amp;#39;belbos&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Merode&amp;#39;}, {&amp;#39;moedre&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Blankenberge&amp;#39;}, {&amp;#39;Blankenberge&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Luttre&amp;#39;}, {&amp;#39;lutter&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Lede&amp;#39;}, {&amp;#39;Deel&amp;#39;, &amp;#39;elde&amp;#39;, &amp;#39;leed&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Wavre&amp;#39;}, {&amp;#39;verwa&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Eine&amp;#39;}, {&amp;#39;eine&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Tienen&amp;#39;}, {&amp;#39;ineten&amp;#39;, &amp;#39;tienen&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Aalst&amp;#39;}, {&amp;#39;slaat&amp;#39;, &amp;#39;staal&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Coo&amp;#39;}, {&amp;#39;C.O.O.&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Mollem&amp;#39;, &amp;#39;Lommel&amp;#39;}, {&amp;#39;mollem&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Simonis&amp;#39;}, {&amp;#39;simonis&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Puurs&amp;#39;}, {&amp;#39;Pruus&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;div class="details-collapse" onclick="document.getElementById('details-6').open = false;"&gt;
 &lt;em&gt;&lt;u&gt;Click to collapse&lt;/u&gt;&lt;/em&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 &lt;/details&gt;
 &lt;div class="details-preview"&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Jette&amp;#39;}, {&amp;#39;tetje&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Temse&amp;#39;}, {&amp;#39;smete&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Lierde&amp;#39;}, {&amp;#39;leider&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Leman&amp;#39;}, {&amp;#39;lamen&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Ternat&amp;#39;}, {&amp;#39;ratten&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Kijkuit&amp;#39;}, {&amp;#39;kijkuit&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Boom&amp;#39;}, {&amp;#39;boom&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Godinne&amp;#39;}, {&amp;#39;doening&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Bleret&amp;#39;}, {&amp;#39;bretel&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Muizen&amp;#39;}, {&amp;#39;muizen&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Asse&amp;#39;}, {&amp;#39;asse&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Landen&amp;#39;}, {&amp;#39;landen&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Weerde&amp;#39;}, {&amp;#39;weerde&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Mol&amp;#39;}, {&amp;#39;mol&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Geel&amp;#39;}, {&amp;#39;leeg&amp;#39;, &amp;#39;Geel&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Sint-Niklaas&amp;#39;}, {&amp;#39;Sint-Niklaas&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Drongen&amp;#39;}, {&amp;#39;gronden&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Welle&amp;#39;}, {&amp;#39;welle&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Ruisbroek&amp;#39;}, {&amp;#39;ruisbroek&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Zele&amp;#39;}, {&amp;#39;zeel&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Meiser&amp;#39;}, {&amp;#39;misere&amp;#39;, &amp;#39;remise&amp;#39;, &amp;#39;eremis&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Spa&amp;#39;}, {&amp;#39;SAP&amp;#39;, &amp;#39;pas&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Menen&amp;#39;}, {&amp;#39;menne&amp;#39;, &amp;#39;nemen&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Lens&amp;#39;}, {&amp;#39;snel&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Tielt&amp;#39;}, {&amp;#39;titel&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Eupen&amp;#39;}, {&amp;#39;peune&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Engis&amp;#39;}, {&amp;#39;signe&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Eichem&amp;#39;}, {&amp;#39;chemie&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Ekeren&amp;#39;}, {&amp;#39;ne keer&amp;#39;, &amp;#39;nekeer&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Niel&amp;#39;}, {&amp;#39;lein&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Manage&amp;#39;}, {&amp;#39;gemaan&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Ronet&amp;#39;}, {&amp;#39;tenor&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Lot&amp;#39;}, {&amp;#39;lot&amp;#39;, &amp;#39;tol&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Essen&amp;#39;}, {&amp;#39;se-n-se&amp;#39;, &amp;#39;sense&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Lobbes&amp;#39;}, {&amp;#39;belbos&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Merode&amp;#39;}, {&amp;#39;moedre&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Blankenberge&amp;#39;}, {&amp;#39;Blankenberge&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Luttre&amp;#39;}, {&amp;#39;lutter&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Lede&amp;#39;}, {&amp;#39;Deel&amp;#39;, &amp;#39;elde&amp;#39;, &amp;#39;leed&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Wavre&amp;#39;}, {&amp;#39;verwa&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Eine&amp;#39;}, {&amp;#39;eine&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Tienen&amp;#39;}, {&amp;#39;ineten&amp;#39;, &amp;#39;tienen&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Aalst&amp;#39;}, {&amp;#39;slaat&amp;#39;, &amp;#39;staal&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Coo&amp;#39;}, {&amp;#39;C.O.O.&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Mollem&amp;#39;, &amp;#39;Lommel&amp;#39;}, {&amp;#39;mollem&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Simonis&amp;#39;}, {&amp;#39;simonis&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;({&amp;#39;Puurs&amp;#39;}, {&amp;#39;Pruus&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;div class="fade-overlay"&gt;&lt;/div&gt;
 &lt;/div&gt;
 &lt;div class="details-toggle" onclick="document.getElementById('details-6').open = true;"&gt;
 &lt;em&gt;&lt;u&gt;Click to expand&lt;/u&gt;&lt;/em&gt;
 &lt;/div&gt;
&lt;/div&gt;

&lt;style&gt;
.details-wrapper {
 position: relative;
}

.details-wrapper details {
 margin-top: 0;
 margin-bottom: 0;
}

.details-content {
 margin-top: 0.75rem;
}

.details-preview {
 position: relative;
 max-height: 200px;
 overflow: hidden;
 margin-top: 0.75rem;
 margin-bottom: 0.5rem;
}

.details-preview pre {
 margin-top: 0 !important;
}

.details-content pre {
 margin-bottom: 0 !important;
}

.details-preview .fade-overlay {
 position: absolute;
 bottom: 0;
 left: 0;
 right: 0;
 height: 60px;
 background: linear-gradient(transparent, var(--background, #f8f9fa));
 pointer-events: none;
}

.details-toggle {
 text-align: center;
 margin-top: 0.25rem;
 font-size: 0.7em;
 color: var(--text-color, #aaa);
 cursor: pointer;
 opacity: 0.6;
}

.details-summary {
 display: none;
}

.details-collapse {
 text-align: center;
 margin-top: 0.25rem;
 font-size: 0.7em;
 color: var(--text-color, #aaa);
 cursor: pointer;
 opacity: 0.6;
}

.details-wrapper details[open] + .details-preview {
 display: none;
}

.details-wrapper details[open] + .details-preview + .details-toggle {
 display: none;
}

.details-wrapper details:not([open]) .details-content {
 display: none;
}

 
@media (prefers-color-scheme: dark) {
 .details-preview .fade-overlay {
 background: linear-gradient(transparent, var(--background, #1a1a1a));
 }
 
 .details-toggle {
 color: var(--text-color, #888);
 }
 
 .details-collapse {
 color: var(--text-color, #888);
 }
}
&lt;/style&gt;
&lt;h3 id="multi-word-anagrams"&gt;Multi-word anagrams&lt;/h3&gt;
&lt;p&gt;Above, we only look at one-to-one mappings where a shuffling of one Flemish dialect word gives us a Belgian railway station name. What if we want to have a combination of two (or more) words that, when shuffled together, gives us a station name?&lt;/p&gt;
&lt;h4 id="bruteforce"&gt;Bruteforce&lt;/h4&gt;
&lt;p&gt;A bruteforce approach to multi-word anagrams is straightforward: for anagrams of one word list that are made up of $n$ words of the other wordlist, we can take all unordered combinations of $n$ keys of one alphabetic map with replacement, combine them, and check if this combined key is present in the other alphabetic map:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;from&lt;/span&gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;itertools&lt;/span&gt; &lt;span style="font-weight:bold;text-decoration:underline"&gt;import&lt;/span&gt; combinations_with_replacement &lt;span style="font-weight:bold;text-decoration:underline"&gt;as&lt;/span&gt; cwr
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;def&lt;/span&gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;combine_keys&lt;/span&gt;(*keys):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="font-weight:bold;text-decoration:underline"&gt;return&lt;/span&gt; &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&amp;#34;&lt;/span&gt;.join(&lt;span style="font-weight:bold;font-style:italic"&gt;sorted&lt;/span&gt;(&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&amp;#34;&lt;/span&gt;.join(keys)))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;def&lt;/span&gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;n_agrams&lt;/span&gt;(n):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	keys = &lt;span style="font-weight:bold;font-style:italic"&gt;list&lt;/span&gt;(grouped_wordlist)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="font-weight:bold;text-decoration:underline"&gt;for&lt;/span&gt; key &lt;span style="font-weight:bold"&gt;in&lt;/span&gt; cwr(keys, n):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		word_sets = (grouped_wordlist[k] &lt;span style="font-weight:bold;text-decoration:underline"&gt;for&lt;/span&gt; k &lt;span style="font-weight:bold"&gt;in&lt;/span&gt; key)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="font-weight:bold;text-decoration:underline"&gt;if&lt;/span&gt; (combined_key := combine_keys(*key)) &lt;span style="font-weight:bold"&gt;in&lt;/span&gt; grouped_stations:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			stations = grouped_stations[combined_key]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="font-weight:bold;font-style:italic"&gt;print&lt;/span&gt;(&lt;span style="color:#666;font-style:italic"&gt;f&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;{&lt;/span&gt;stations&lt;span style="color:#666;font-style:italic"&gt;}&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt; = &lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;{&lt;/span&gt;&lt;span style="font-weight:bold;font-style:italic"&gt;list&lt;/span&gt;(word_sets)&lt;span style="color:#666;font-style:italic"&gt;}&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For $n = 2$, we get 1078 different combinations:&lt;/p&gt;

&lt;div class="details-wrapper"&gt;
 &lt;details id="details-7"&gt;
 &lt;summary class="details-summary"&gt;Details&lt;/summary&gt;
 &lt;div class="details-content"&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#39;Diesdelle&amp;#39;} = {&amp;#39;dees&amp;#39;} + {&amp;#39;dille&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#39;Kapelle-op-den-Bos&amp;#39;} = {&amp;#39;bedelke&amp;#39;} + {&amp;#39;salonpop&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#39;Kapelle-op-den-Bos&amp;#39;} = {&amp;#39;poekele&amp;#39;, &amp;#39;poeleke&amp;#39;} + {&amp;#39;plonsbad&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#39;Kapelle-op-den-Bos&amp;#39;} = {&amp;#39;sloppel&amp;#39;} + {&amp;#39;bakendoe&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#39;Kortemark&amp;#39;} = {&amp;#39;karot&amp;#39;} + {&amp;#39;merk&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#39;Kortemark&amp;#39;} = {&amp;#39;krak&amp;#39;} + {&amp;#39;om ter&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#39;Kortemark&amp;#39;} = {&amp;#39;kram&amp;#39;} + {&amp;#39;kroet&amp;#39;, &amp;#39;krote&amp;#39;, &amp;#39;roket&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#39;Kortemark&amp;#39;} = {&amp;#39;kroam&amp;#39;, &amp;#39;kraom&amp;#39;} + {&amp;#39;trek&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#39;Kortemark&amp;#39;} = {&amp;#39;rakker&amp;#39;, &amp;#39;kraker&amp;#39;} + {&amp;#39;mot&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#39;Kortemark&amp;#39;} = {&amp;#39;ram&amp;#39;} + {&amp;#39;kroket&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#39;Landskouter&amp;#39;} = {&amp;#39;dals&amp;#39;} + {&amp;#39;konteur&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#39;Landskouter&amp;#39;} = {&amp;#39;dokteur&amp;#39;} + {&amp;#39;lans&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#39;Landskouter&amp;#39;} = {&amp;#39;duks&amp;#39;} + {&amp;#39;lantoer&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#39;Landskouter&amp;#39;} = {&amp;#39;dutsen&amp;#39;} + {&amp;#39;akrol&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#39;Landskouter&amp;#39;} = {&amp;#39;kadul&amp;#39;} + {&amp;#39;storen&amp;#39;, &amp;#39;roste(n)&amp;#39;, &amp;#39;rotsen&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;div class="details-collapse" onclick="document.getElementById('details-7').open = false;"&gt;
 &lt;em&gt;&lt;u&gt;Click to collapse&lt;/u&gt;&lt;/em&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 &lt;/details&gt;
 &lt;div class="details-preview"&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#39;Diesdelle&amp;#39;} = {&amp;#39;dees&amp;#39;} + {&amp;#39;dille&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#39;Kapelle-op-den-Bos&amp;#39;} = {&amp;#39;bedelke&amp;#39;} + {&amp;#39;salonpop&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#39;Kapelle-op-den-Bos&amp;#39;} = {&amp;#39;poekele&amp;#39;, &amp;#39;poeleke&amp;#39;} + {&amp;#39;plonsbad&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#39;Kapelle-op-den-Bos&amp;#39;} = {&amp;#39;sloppel&amp;#39;} + {&amp;#39;bakendoe&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#39;Kortemark&amp;#39;} = {&amp;#39;karot&amp;#39;} + {&amp;#39;merk&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#39;Kortemark&amp;#39;} = {&amp;#39;krak&amp;#39;} + {&amp;#39;om ter&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#39;Kortemark&amp;#39;} = {&amp;#39;kram&amp;#39;} + {&amp;#39;kroet&amp;#39;, &amp;#39;krote&amp;#39;, &amp;#39;roket&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#39;Kortemark&amp;#39;} = {&amp;#39;kroam&amp;#39;, &amp;#39;kraom&amp;#39;} + {&amp;#39;trek&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#39;Kortemark&amp;#39;} = {&amp;#39;rakker&amp;#39;, &amp;#39;kraker&amp;#39;} + {&amp;#39;mot&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#39;Kortemark&amp;#39;} = {&amp;#39;ram&amp;#39;} + {&amp;#39;kroket&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#39;Landskouter&amp;#39;} = {&amp;#39;dals&amp;#39;} + {&amp;#39;konteur&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#39;Landskouter&amp;#39;} = {&amp;#39;dokteur&amp;#39;} + {&amp;#39;lans&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#39;Landskouter&amp;#39;} = {&amp;#39;duks&amp;#39;} + {&amp;#39;lantoer&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#39;Landskouter&amp;#39;} = {&amp;#39;dutsen&amp;#39;} + {&amp;#39;akrol&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&amp;#39;Landskouter&amp;#39;} = {&amp;#39;kadul&amp;#39;} + {&amp;#39;storen&amp;#39;, &amp;#39;roste(n)&amp;#39;, &amp;#39;rotsen&amp;#39;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;div class="fade-overlay"&gt;&lt;/div&gt;
 &lt;/div&gt;
 &lt;div class="details-toggle" onclick="document.getElementById('details-7').open = true;"&gt;
 &lt;em&gt;&lt;u&gt;Click to expand&lt;/u&gt;&lt;/em&gt;
 &lt;/div&gt;
&lt;/div&gt;

&lt;style&gt;
.details-wrapper {
 position: relative;
}

.details-wrapper details {
 margin-top: 0;
 margin-bottom: 0;
}

.details-content {
 margin-top: 0.75rem;
}

.details-preview {
 position: relative;
 max-height: 200px;
 overflow: hidden;
 margin-top: 0.75rem;
 margin-bottom: 0.5rem;
}

.details-preview pre {
 margin-top: 0 !important;
}

.details-content pre {
 margin-bottom: 0 !important;
}

.details-preview .fade-overlay {
 position: absolute;
 bottom: 0;
 left: 0;
 right: 0;
 height: 60px;
 background: linear-gradient(transparent, var(--background, #f8f9fa));
 pointer-events: none;
}

.details-toggle {
 text-align: center;
 margin-top: 0.25rem;
 font-size: 0.7em;
 color: var(--text-color, #aaa);
 cursor: pointer;
 opacity: 0.6;
}

.details-summary {
 display: none;
}

.details-collapse {
 text-align: center;
 margin-top: 0.25rem;
 font-size: 0.7em;
 color: var(--text-color, #aaa);
 cursor: pointer;
 opacity: 0.6;
}

.details-wrapper details[open] + .details-preview {
 display: none;
}

.details-wrapper details[open] + .details-preview + .details-toggle {
 display: none;
}

.details-wrapper details:not([open]) .details-content {
 display: none;
}

 
@media (prefers-color-scheme: dark) {
 .details-preview .fade-overlay {
 background: linear-gradient(transparent, var(--background, #1a1a1a));
 }
 
 .details-toggle {
 color: var(--text-color, #888);
 }
 
 .details-collapse {
 color: var(--text-color, #888);
 }
}
&lt;/style&gt;
&lt;p&gt;For $n \geq 3$, however, things start to slow down drastically. This naive bruteforce approach could further be optimised through some tricks to disregard impossible candidates, but as $n$ increases this would be &lt;a href="https://en.wiktionary.org/wiki/dweilen_met_de_kraan_open"&gt;&lt;em&gt;&amp;ldquo;mopping with the faucet running&amp;rdquo;&lt;/em&gt;&lt;/a&gt;, as we say in Dutch. For $n \geq 3$, we could use a specialised data structure.&lt;/p&gt;
&lt;h4 id="anatrees"&gt;Anatrees&lt;/h4&gt;
&lt;p&gt;An &lt;a href="https://en.wikipedia.org/wiki/Anatree"&gt;anatree&lt;/a&gt;&lt;label for="sidenote-8" class="sidenote-number"&gt;&lt;/label&gt;&lt;input type="checkbox" id="sidenote-8" class="sidenote-toggle"&gt;&lt;span class="sidenote"&gt;Charles Reams. 2012. &lt;strong&gt;Anatree: A Fast Data Structure for Anagrams.&lt;/strong&gt; ACM J. Exp. Algorithmics 17, Article 1.1 (2012), 16 pages. &lt;a href="https://doi.org/10.1145/2133803.2133804"&gt;https://doi.org/10.1145/2133803.2133804&lt;/a&gt;&lt;/span&gt; is a directed edge-labelled tree that describes a set of words. Internal nodes of the anatree represent symbols of an alphabet, and the leaves represent subsets of the set of words. Edges are labelled with positive integers, including zero. Paths of nodes $n_1, \ldots, n_l$ from the root $n_1$ to a leaf $n_l$ along edges labelled with integers $e_1, \ldots, e_l$ arrive at a leaf $n_l$, representing the subset of words that contains exactly $e_i$ times the symbol $n_i$, for all nodes on its path.&lt;/p&gt;

&lt;figure&gt;
 &lt;img src="http://patrick.vanderspie.gl/posts/scrambled-stations/anatree.svg" alt="One possible anatree for the same set of words {&amp;#39;odd&amp;#39;, &amp;#39;goo&amp;#39;, &amp;#39;dog&amp;#39;, &amp;#39;fog&amp;#39;, &amp;#39;loo&amp;#39;} as used in the original anatree paper, using an own implementation of anatrees and Graphviz" class="invert-dark" loading="lazy" /&gt;
 &lt;figcaption&gt;One possible anatree for the same set of words {&amp;#39;odd&amp;#39;, &amp;#39;goo&amp;#39;, &amp;#39;dog&amp;#39;, &amp;#39;fog&amp;#39;, &amp;#39;loo&amp;#39;} as used in the original anatree paper, using an own implementation of anatrees and Graphviz&lt;/figcaption&gt;
&lt;/figure&gt;


&lt;p&gt;The anatree shown above is just one possible anatree for a certain set of words, as there is not just &lt;em&gt;one&lt;/em&gt; anatree for a given set. You could have different strategies to pick which character a certain node represents, each resulting in a different anatree. To generate the figure used above, at every step of construction, the most frequently occurring but not yet considered character of the remaining set of words is used as the symbol for the next node. Creating the anatree for the Flemish wordlist resulted in a tree consisting of 172.210 nodes, if we use the least frequent character first. If we use the most frequent character first, we get 127.534 nodes. Other strategies might lead to further reduction of the size of the anatree.&lt;/p&gt;
&lt;p&gt;One approach to find multi-word anagrams of one specific train station is starting with that station&amp;rsquo;s bag of letters and using it as a &amp;ldquo;budget&amp;rdquo; while traversing the anatree of dialect words. For a train station with two occurrences of the letter &lt;em&gt;e&lt;/em&gt;, for example, we could explore paths that contain at most two &lt;em&gt;e&lt;/em&gt;&amp;rsquo;s, subtracting &amp;ldquo;spent&amp;rdquo; &lt;em&gt;e&lt;/em&gt;&amp;rsquo;s from our available budget. After reaching a leaf node on a partial budget, we could explore other paths with the remaining budget. If we are able to reach another leaf with that remaining budget, we have found a multi-word anagram.&lt;/p&gt;
&lt;p&gt;I did not implement this multi-word anagram algorithm in the end, as I&amp;rsquo;m not sure on performance (you&amp;rsquo;d have to perform &lt;em&gt;a lot&lt;/em&gt; of different anatree traversals to find multi-word anagrams, and there are a lot of different ways in which you could &amp;ldquo;spend&amp;rdquo; your budget). Exploring this idea already took a bit more time than expected, and I was happy with my $n = 2$ anagram list.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="side-notes"&gt;Side notes&lt;/h2&gt;
&lt;h3 id="displaying-anagrams"&gt;Displaying anagrams&lt;/h3&gt;
&lt;p&gt;To display these anagrams (and eventually also the title of this post), I wanted to imitate the classic Belgian railway station name signs using &lt;code&gt;CSS&lt;/code&gt;. Looking for the typeface, I landed on a &lt;a href="https://www.hgbtf.net/viewtopic.php?t=13372"&gt;2017 thread on a Belgian train forum&lt;/a&gt; where a poster named &lt;code&gt;Nadieeh&lt;/code&gt; found out that the Brussels-based graphic design studio &lt;a href="https://speculoos.com/"&gt;Speculoos&lt;/a&gt; created &lt;em&gt;Alfphabet&lt;/em&gt;, a digitised version of the typeface I was looking for. I ended up downloading the typeface from the &lt;a href="https://osp.kitchen/foundry/alfphabet/tree/master/"&gt;osp.kitchen&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;FONTLOG.txt&lt;/code&gt;, which is included with a download of &lt;em&gt;Alfphabet&lt;/em&gt;, also contains some typical Belgian history:
&lt;div class="quote-block"&gt;
 &lt;blockquote class="quote-content"&gt;The Alfphabet family is based on the Belgian road signage called &amp;lsquo;Alphabet&amp;rsquo; in French and &amp;lsquo;Alfabet&amp;rsquo; in Flemish. It was introduced in 1945 by 3M system working for the Marshall plan after the end of the war. In 1975, it was replaced by the Swiss SNV fonts, but is still in used randomly by the Belgian railroad and Charleroi&amp;rsquo;s metro. In the early nineties, &lt;strong&gt;Pierre Huyghebaert was able to copy the original plates just before the split of the national office of the roads &amp;lsquo;Fond des Routes&amp;rsquo; in three regional entities and the burial of the documents deep into regional archives.&lt;/strong&gt;&lt;/blockquote&gt;
&lt;/div&gt;&lt;div class="quote-source-link"&gt;
 &lt;a href="https://osp.kitchen/foundry/alfphabet/tree/master/FONTLOG.txt#project-detail-files" target="_blank" rel="noopener"&gt;Alfphabet FONTLOG.txt&lt;/a&gt;
&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;For the background colour, I used a colour picker on a picture of an old railway station sign to end up with &lt;code&gt;rgb(0, 33, 84)&lt;/code&gt;, and with some trial and error managed to get a white rounded border to simulate old railway signage:&lt;/p&gt;
&lt;div class="alfphabet-display alfphabet-scale-medium"&gt;
Alfphabet Typeface
&lt;/div&gt;
&lt;h3 id="shortest-stations"&gt;Shortest stations&lt;/h3&gt;
&lt;p&gt;Going through the &lt;code&gt;CSV&lt;/code&gt; of train stations with a friend, we were curious about the shortest name for a station in Belgium, which turns out to be &lt;a href="https://en.wikipedia.org/wiki/Sy_railway_station"&gt;&lt;em&gt;Sy&lt;/em&gt;&lt;/a&gt; (part of Ferrières near the Ourthe river):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ awk &lt;span style="color:#666;font-style:italic"&gt;&amp;#39;{ print length, $0 }&amp;#39;&lt;/span&gt; railway_stations.txt | sort -n | cut -d&lt;span style="color:#666;font-style:italic"&gt;&amp;#34; &amp;#34;&lt;/span&gt; -f2- | head -n 5
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Sy
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Ans
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Ath
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Aye
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Coo
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;a href="https://nl.wikipedia.org/wiki/Station_Sy"&gt;Dutch Wikipedia page&lt;/a&gt; claims that Sy is the shortest name for a train station in the whole Benelux.&lt;/p&gt;
&lt;div class="alfphabet-display alfphabet-scale-small"&gt;
Sy
&lt;/div&gt;
&lt;h3 id="bucket-lists"&gt;Bucket lists&lt;/h3&gt;
&lt;p&gt;I recently read Adam Aaronson&amp;rsquo;s &lt;a href="https://aaronson.org/blog/i-drank-every-cocktail"&gt;&amp;quot;&lt;em&gt;I Drank Every Cocktail&lt;/em&gt;&amp;quot;&lt;/a&gt; about how he managed to drink all &lt;a href="https://en.wikipedia.org/wiki/List_of_IBA_official_cocktails"&gt;&amp;ldquo;IBA official cocktails&amp;rdquo;&lt;/a&gt; spread over a couple of years; and I loved his story.&lt;/p&gt;
&lt;p&gt;Based on his journey, I wonder how long it would take me to visit all Belgian railway stations. Not just passing the station by train, but to actually visit and take a picture with one of the station name signs.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ xan filter &lt;span style="color:#666;font-style:italic"&gt;&amp;#39;col(&amp;#34;country-code&amp;#34;) eq &amp;#34;be&amp;#34;&amp;#39;&lt;/span&gt; railway_stations.csv | &lt;span style="color:#666;font-style:italic"&gt;\ &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; xan count
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;578
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Almost 600 stations spread over a couple of years is certainly not impossible, I guess. Who knows, maybe I&amp;rsquo;ll be able to post my own &lt;em&gt;&amp;ldquo;I Visited Every Station&amp;rdquo;&lt;/em&gt; eventually!&lt;/p&gt;</description></item><item><title>Cryptmanteaux</title><link>http://patrick.vanderspie.gl/posts/cryptmanteaux/</link><pubDate>Sun, 01 Jun 2025 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/posts/cryptmanteaux/</guid><description>&lt;p&gt;I recently learned through Wikipedia and Wiktionary that the word &lt;a href="https://en.wiktionary.org/wiki/electrocution"&gt;&lt;em&gt;electrocution&lt;/em&gt;&lt;/a&gt; is a &lt;a href="https://en.wikipedia.org/wiki/Portmanteau"&gt;portmanteau&lt;/a&gt; of &lt;em&gt;electro-&lt;/em&gt; and &lt;em&gt;execution&lt;/em&gt;.&lt;label for="sidenote-0" class="sidenote-number"&gt;&lt;/label&gt;&lt;input type="checkbox" id="sidenote-0" class="sidenote-toggle"&gt;&lt;span class="sidenote"&gt;&lt;em&gt;The New York Times&lt;/em&gt; hating the word &lt;em&gt;electrocution&lt;/em&gt;, and Thomas Edison preferring alternative words like &lt;em&gt;dynamort&lt;/em&gt;, are also some fun facts found &lt;a href="https://en.wikipedia.org/wiki/Electrocution#Etymology"&gt;on Wikipedia&lt;/a&gt;.&lt;/span&gt; This makes sense in hindsight, but it never clicked before that the &lt;em&gt;-cution&lt;/em&gt; part of &lt;em&gt;electrocution&lt;/em&gt; comes from &lt;em&gt;execution&lt;/em&gt;. As I like short word puzzles (like &lt;a href="https://www.minutecryptic.com/"&gt;Minute Cryptic&lt;/a&gt; and &lt;a href="https://www.nytimes.com/games/connections"&gt;Connections&lt;/a&gt;), I wondered if there were any similar word games that use portmanteaux as their main mechanic.&lt;/p&gt;
&lt;p&gt;In cryptic crosswords, you find words based on clues which themselves are kind of word puzzles consisting of a definition (typically at the start or end of a clue) and the wordplay (giving instructions on how to get the answer based on the clue). As an easy example clue, which I &lt;a href="https://github.com/bodasadallah/decrypting-crosswords/blob/main/data/200_clues.csv"&gt;found online&lt;/a&gt;:&lt;/p&gt;
&lt;div class="quote-block"&gt;
 &lt;blockquote class="quote-content"&gt;Error concealed by city police (4)&lt;/blockquote&gt;
&lt;/div&gt;&lt;div class="quote-source-link"&gt;
 &lt;a href="https://github.com/bodasadallah/decrypting-crosswords/blob/main/data/200_clues.csv#L32" target="_blank" rel="noopener"&gt;decrypting-crosswords&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Here, &lt;em&gt;&amp;ldquo;error&amp;rdquo;&lt;/em&gt; is the definition: we&amp;rsquo;re looking for an alternative word for &lt;em&gt;&amp;ldquo;error&amp;rdquo;&lt;/em&gt;. The words &lt;em&gt;&amp;ldquo;concealed by&amp;rdquo;&lt;/em&gt; indicate that the four-letter word we&amp;rsquo;re looking for is hidden inside the words &lt;em&gt;&amp;ldquo;ci&lt;strong&gt;ty po&lt;/strong&gt;lice&amp;rdquo;&lt;/em&gt;. Other possible types of wordplay include anagrams, double definitions, homophones, and more (as seen on the &lt;a href="https://www.minutecryptic.com/guide"&gt;Minute Cryptic guide&lt;/a&gt;.)&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Combining portmanteaux, cryptic crosswords, and Connections gives us a word game where you need to find two related portmanteaux through four cryptic clues that describe four base words. By correctly matching pairs of base words, you find the two hidden portmanteaux. Try it out, and check &lt;a href="#walkthrough"&gt;the walkthrough&lt;/a&gt; afterwards!&lt;/p&gt;


&lt;div class="word-game" id="game-crypt"&gt;
 &lt;style&gt;
 .word-game {
 max-width: 900px;
 margin: 20px auto;
 padding: 20px;
 border: 2px solid #e1e5e9;
 border-radius: 12px;
 background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
 font-family: var(--), Tahoma, Geneva, Verdana, sans-serif;
 box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
 }

 .word-game h3 {
 text-align: center;
 color: #2c3e50;
 margin-bottom: 20px;
 font-size: 1.5em;
 }

 .clues-container {
 display: grid;
 grid-template-columns: 1fr 1fr;
 gap: 15px;
 margin-bottom: 25px;
 }

 .clue-box {
 background: white;
 padding: 15px;
 border-radius: 8px;
 border: 1px solid color-mix(in srgb, var(--highlight, #3498db) 25%, transparent);
 box-shadow: 0 2px 4px rgba(0, 0, 0, 0.06);
 transition: transform 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
 }

 .clue-box:hover {
 transform: translateY(-2px);
 border-color: color-mix(in srgb, var(--highlight, #3498db) 55%, transparent);
 box-shadow: 0 4px 8px rgba(0, 0, 0, 0.12);
 }

 .clue-number {
 display: inline-block;
 font-weight: bold;
 color: var(--highlight, #3498db);
 background: color-mix(in srgb, var(--highlight, #3498db) 12%, transparent);
 padding: 2px 8px;
 border-radius: 999px;
 font-size: 0.7em;
 letter-spacing: 0.06em;
 text-transform: uppercase;
 margin-bottom: 8px;
 }

 .clue-text {
 color: #2c3e50;
 line-height: 1;
 font-size: 0.8em;
 }

 .answers-section {
 background: white;
 padding: 20px;
 border-radius: 8px;
 margin-bottom: 20px;
 }

 .word-lengths-info {
 text-align: center;
 margin-bottom: 20px;
 padding: 12px;
 background: #f8f9fa;
 border: 1px solid #dee2e6;
 border-radius: 6px;
 color: #495057;
 font-size: 0.9em;
 font-weight: 500;
 }

 .answer-inputs {
 display: grid;
 grid-template-columns: 1fr 1fr;
 gap: 15px;
 margin-bottom: 20px;
 }

 .answer-group {
 display: flex;
 flex-direction: column;
 }

 .answer-group label {
 font-weight: bold;
 color: #2c3e50;
 margin-bottom: 8px;
 font-size: 0.8em;
 }

 .answer-group input {
 padding: 12px;
 border: 2px solid #ddd;
 border-radius: 6px;
 font-size: 0.8em;
 transition: border-color 0.2s ease;
 }

 .answer-group input:focus {
 outline: none;
 border-color: #3498db;
 box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.1);
 }

 .answer-group input.correct {
 border-color: #27ae60;
 background-color: #d5f4e6;
 }

 .answer-group input.incorrect {
 border-color: #e74c3c;
 background-color: #fdf2f2;
 }

 .game-controls {
 text-align: center;
 }

 .check-btn {
 background: linear-gradient(135deg, var(--highlight, #3498db), color-mix(in srgb, var(--highlight, #3498db) 80%, black));
 color: white;
 border: none;
 padding: 10px 20px;
 font-size: 0.8em;
 border-radius: 6px;
 cursor: pointer;
 transition: all 0.2s ease;
 margin-right: 10px;
 }

 .check-btn:hover {
 background: linear-gradient(135deg, color-mix(in srgb, var(--highlight, #3498db) 80%, black), color-mix(in srgb, var(--highlight, #3498db) 65%, black));
 transform: translateY(-1px);
 }

 .reset-btn {
 background: linear-gradient(135deg, #95a5a6, #7f8c8d);
 color: white;
 border: none;
 margin-top: 10px;
 padding: 10px 20px;
 font-size: 0.8em;
 border-radius: 6px;
 cursor: pointer;
 transition: all 0.2s ease;
 }

 .reset-btn:hover {
 background: linear-gradient(135deg, #7f8c8d, #6c7b7d);
 transform: translateY(-1px);
 }

 .feedback {
 margin-top: 15px;
 padding: 15px;
 border-radius: 6px;
 text-align: center;
 font-weight: bold;
 display: none;
 }

 .feedback.success {
 background-color: #d5f4e6;
 color: #27ae60;
 border: 1px solid #27ae60;
 }

 .feedback.partial {
 background-color: #fff3cd;
 color: #856404;
 border: 1px solid #ffc107;
 }

 .feedback.error {
 background-color: #fdf2f2;
 color: #e74c3c;
 border: 1px solid #e74c3c;
 }

 
 .dark .word-game {
 border: 2px solid #3a3a3a;
 background: linear-gradient(135deg, #2c2c2c 0%, #1e1e1e 100%);
 box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
 }

 .dark .word-game h3 {
 color: var(--content-primary);
 }

 .dark .clue-box {
 background: #2a2a2a;
 border: 1px solid color-mix(in srgb, var(--highlight, #4a90e2) 35%, transparent);
 box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
 }

 .dark .clue-box:hover {
 border-color: color-mix(in srgb, var(--highlight, #4a90e2) 70%, transparent);
 box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
 }

 .dark .clue-number {
 color: color-mix(in srgb, var(--highlight, #4a90e2) 75%, white);
 background: color-mix(in srgb, var(--highlight, #4a90e2) 22%, transparent);
 }

 .dark .clue-text {
 color: var(--content-primary);
 }

 .dark .answers-section {
 background: #2a2a2a;
 }

 .dark .word-lengths-info {
 background: #333333;
 border: 1px solid #444444;
 color: var(--content-secondary);
 }

 .dark .answer-group label {
 color: var(--content-primary);
 }

 .dark .answer-group input {
 background: #333333;
 border: 2px solid #555555;
 color: var(--content-primary);
 }

 .dark .answer-group input:focus {
 border-color: #4a90e2;
 box-shadow: 0 0 0 3px rgba(74, 144, 226, 0.2);
 }

 .dark .answer-group input.correct {
 border-color: #4ade80;
 background-color: #1f2937;
 }

 .dark .answer-group input.incorrect {
 border-color: #f87171;
 background-color: #2d1b1b;
 }

 .dark .feedback.success {
 background-color: #1f2937;
 color: #4ade80;
 border: 1px solid #4ade80;
 }

 .dark .feedback.partial {
 background-color: #2d2618;
 color: #fbbf24;
 border: 1px solid #fbbf24;
 }

 .dark .feedback.error {
 background-color: #2d1b1b;
 color: #f87171;
 border: 1px solid #f87171;
 }

 @media (max-width: 600px) {
 .clues-container,
 .answer-inputs {
 grid-template-columns: 1fr;
 }
 
 .word-game {
 margin: 10px;
 padding: 15px;
 }
 }
 &lt;/style&gt;

 
 
 &lt;div class="clues-container"&gt;
 &lt;div class="clue-box" id="clue-1"&gt;
 &lt;div class="clue-number"&gt;Clue 1&lt;/div&gt;
 &lt;div class="clue-text"&gt;Fast brake ruined morning meal. (9)&lt;/div&gt;
 &lt;/div&gt;
 &lt;div class="clue-box" id="clue-2"&gt;
 &lt;div class="clue-number"&gt;Clue 2&lt;/div&gt;
 &lt;div class="clue-text"&gt;Dairy product makes one grin! (6)&lt;/div&gt;
 &lt;/div&gt;
 &lt;div class="clue-box" id="clue-3"&gt;
 &lt;div class="clue-number"&gt;Clue 3&lt;/div&gt;
 &lt;div class="clue-text"&gt;Noon activity sounds like lunging. (8)&lt;/div&gt;
 &lt;/div&gt;
 &lt;div class="clue-box" id="clue-4"&gt;
 &lt;div class="clue-number"&gt;Clue 4&lt;/div&gt;
 &lt;div class="clue-text"&gt;Sandwiches for German citizens. (10)&lt;/div&gt;
 &lt;/div&gt;
 &lt;/div&gt;

 &lt;div class="answers-section"&gt;
 &lt;div class="word-lengths-info"&gt;
 Find two portmanteaux: one with (9) letters and one with (13) letters!
 &lt;/div&gt;

 &lt;div class="answer-inputs"&gt;
 &lt;div class="answer-group"&gt;
 &lt;label for="answer1-crypt"&gt;Answer 1:&lt;/label&gt;
 &lt;input type="text" id="answer1-crypt" placeholder="Enter your first answer"&gt;
 &lt;/div&gt;
 &lt;div class="answer-group"&gt;
 &lt;label for="answer2-crypt"&gt;Answer 2:&lt;/label&gt;
 &lt;input type="text" id="answer2-crypt" placeholder="Enter your second answer"&gt;
 &lt;/div&gt;
 &lt;/div&gt;

 &lt;div class="game-controls"&gt;
 &lt;button class="check-btn" onclick="checkAnswers('crypt')"&gt;Check Answers&lt;/button&gt;
 &lt;button class="reset-btn" onclick="resetGame('crypt')"&gt;Reset&lt;/button&gt;
 &lt;/div&gt;

 &lt;div class="feedback" id="feedback-crypt"&gt;&lt;/div&gt;
 &lt;/div&gt;

 &lt;script&gt;
 
 window.gameAnswers = window.gameAnswers || {};
 window.gameAnswers['crypt'] = {
 answer1: 'brunching',
 answer2: 'cheeseburgers'
 };

 function checkAnswers(gameId) {
 const input1 = document.getElementById(`answer1-${gameId}`);
 const input2 = document.getElementById(`answer2-${gameId}`);
 const feedback = document.getElementById(`feedback-${gameId}`);
 
 const userAnswer1 = input1.value.toLowerCase().trim();
 const userAnswer2 = input2.value.toLowerCase().trim();
 
 const correctAnswers = window.gameAnswers[gameId];
 
 
 input1.className = '';
 input2.className = '';
 
 let correctCount = 0;
 
 
 if (userAnswer1 === correctAnswers.answer1 || userAnswer1 === correctAnswers.answer2) {
 input1.className = 'correct';
 correctCount++;
 } else if (userAnswer1 !== '') {
 input1.className = 'incorrect';
 }
 
 
 if ((userAnswer2 === correctAnswers.answer1 || userAnswer2 === correctAnswers.answer2) &amp;&amp; userAnswer2 !== userAnswer1) {
 input2.className = 'correct';
 correctCount++;
 } else if (userAnswer2 !== '') {
 input2.className = 'incorrect';
 }
 
 
 feedback.style.display = 'block';
 
 if (correctCount === 2) {
 feedback.className = 'feedback success';
 feedback.textContent = '🎉 Both answers are correct!';
 } else if (correctCount === 1) {
 feedback.className = 'feedback partial';
 feedback.textContent = '👍 One answer is correct!';
 } else {
 feedback.className = 'feedback error';
 feedback.textContent = '❌ Try again!';
 }
 }

 function resetGame(gameId) {
 const input1 = document.getElementById(`answer1-${gameId}`);
 const input2 = document.getElementById(`answer2-${gameId}`);
 const feedback = document.getElementById(`feedback-${gameId}`);
 
 input1.value = '';
 input2.value = '';
 input1.className = '';
 input2.className = '';
 feedback.style.display = 'none';
 }

 
 document.addEventListener('DOMContentLoaded', function() {
 const gameContainer = document.getElementById('game-crypt');
 const inputs = gameContainer.querySelectorAll('input[type="text"]');
 
 inputs.forEach(input =&gt; {
 input.addEventListener('keypress', function(e) {
 if (e.key === 'Enter') {
 checkAnswers('crypt');
 }
 });
 });
 });
 &lt;/script&gt;
&lt;/div&gt;

&lt;hr&gt;
&lt;p&gt;Coming up with a name for this game, I found the made-up portmanteau of &lt;em&gt;cryptic&lt;/em&gt; and &lt;em&gt;portmanteau&lt;/em&gt; to be appropriate: &lt;em&gt;&amp;ldquo;cryptmanteau&amp;rdquo;&lt;/em&gt;. I guess &lt;a href="https://www.themarginalian.org/2012/05/10/mark-twain-helen-keller-plagiarism-originality/"&gt;all ideas really are second-hand&lt;/a&gt;, as Googling this name returns a &lt;a href="https://elsiitk.wordpress.com/wp-content/uploads/2015/03/galaxy-word-games-av-round.pdf"&gt;PDF file dating back to 2015&lt;/a&gt;, containing a game where you are given two cryptic clues for two words that form a portmanteau when combined.&lt;/p&gt;
&lt;p&gt;










&lt;figure class=""&gt;

 &lt;div&gt;&lt;img loading="lazy" alt="Google search results for cryptmanteau, with one result: a pdf titled GALAXY WORD GAMES from the English Literary Society" src=" /posts/cryptmanteaus/google.png"&gt;&lt;/div&gt;

 
 
 &lt;div class="caption-container"&gt;
 &lt;figcaption&gt; Google search results for cryptmanteau, with one result: a pdf titled GALAXY WORD GAMES from the English Literary Society &lt;/figcaption&gt;
 &lt;/div&gt;
 
 
&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The PDF linked above has some fun examples of the concept, like the one quoted below:&lt;/p&gt;
&lt;div class="quote-block"&gt;
 &lt;blockquote class="quote-content"&gt;&lt;ol&gt;
&lt;li&gt;cerebrum puzzled Nabir (5)&lt;/li&gt;
&lt;li&gt;fan in man I acknowledge (6)&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;/div&gt;&lt;div class="quote-source-link"&gt;
 &lt;a href="https://elsiitk.wordpress.com/wp-content/uploads/2015/03/galaxy-word-games-av-round.pdf" target="_blank" rel="noopener"&gt;GALAXY WORD GAMES (AV round)&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;The clues state that the first base word is a five-letter word related to &lt;em&gt;&amp;ldquo;cerebrum&amp;rdquo;&lt;/em&gt;, and that it is an anagram (hinted at by &lt;em&gt;&amp;ldquo;puzzled&amp;rdquo;&lt;/em&gt;) of the word &lt;em&gt;&amp;ldquo;Nabir&amp;rdquo;&lt;/em&gt;, and the second word is a six-letter word related to &lt;em&gt;&amp;ldquo;fan&amp;rdquo;&lt;/em&gt; that we can find &lt;em&gt;&amp;ldquo;in&amp;rdquo;&lt;/em&gt; &lt;em&gt;&amp;quot;&lt;strong&gt;man I ac&lt;/strong&gt;knowledge&amp;quot;&lt;/em&gt;. Combining &lt;em&gt;&amp;ldquo;brain&amp;rdquo;&lt;/em&gt; and &lt;em&gt;&amp;ldquo;maniac&amp;rdquo;&lt;/em&gt; gives us the portmanteau &lt;em&gt;&amp;ldquo;brainiac&amp;rdquo;&lt;/em&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="walkthrough"&gt;Walkthrough&lt;/h2&gt;
&lt;p&gt;In &lt;a href="#game-crypt"&gt;the interactive example&lt;/a&gt; above, we are looking for two related portmanteaux of length 9 and 13, and we are given four cryptic clues for their base words:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;Fast brake ruined morning meal. (9)&lt;/li&gt;
&lt;li&gt;Dairy product makes one grin! (6)&lt;/li&gt;
&lt;li&gt;Noon activity sounds like lunging. (8)&lt;/li&gt;
&lt;li&gt;Sandwiches for German citizens. (10)&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Solving these cryptic clues gives us:&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Breakfast&lt;/strong&gt; (morning meal that is an anagram of &amp;ldquo;fast brake&amp;rdquo;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cheese&lt;/strong&gt; (exclamation when smiling for picture, also dairy product)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lunching&lt;/strong&gt; (noon activity that is a homophone of lunging)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hamburgers&lt;/strong&gt; (double definition: citizens of Hamburg, Germany + meat sandwiches)&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Connecting the right base words gives us the two portmanteaux:&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Breakfast + Lunching → &lt;strong&gt;Brunching&lt;/strong&gt; (9)&lt;/li&gt;
&lt;li&gt;Cheese + Hamburgers → &lt;strong&gt;Cheeseburgers&lt;/strong&gt; (13)&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;Part of the fun is that you might not need to find all four base words from scratch; maybe one from each pair combined with the other clue and figuring out the common theme could be enough to connect the dots.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;I&amp;rsquo;ll certainly be trying to come up with more cryptmanteaux in the future and posting them on my website; &lt;a href="http://patrick.vanderspie.gl/"&gt;send me a message&lt;/a&gt; if you come up with some yourself!&lt;/p&gt;</description></item><item><title>1000 kilometres in 2024</title><link>http://patrick.vanderspie.gl/notes/2025-01-04/</link><pubDate>Sat, 04 Jan 2025 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/notes/2025-01-04/</guid><description>
&lt;img src="http://patrick.vanderspie.gl/notes/2024-cumulative_distance_graph.png" class="invert-dark" loading="lazy" /&gt;


&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://intervals.icu"&gt;intervals.icu API&lt;/a&gt; and &lt;a href="https://jqlang.github.io/jq/"&gt;&lt;code&gt;jq&lt;/code&gt;&lt;/a&gt;:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;BASE_URL&lt;/span&gt;=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;https://intervals.icu/api/v1/athlete&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;OLDEST&lt;/span&gt;=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;2024-01-01&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;NEWEST&lt;/span&gt;=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;2024-12-31&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#888;font-style:italic"&gt;# Fetch activities&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;activities&lt;/span&gt;=&lt;span style="font-weight:bold;text-decoration:underline"&gt;$(&lt;/span&gt;curl -s -u API_KEY:&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$API_KEY&lt;/span&gt; &lt;span style="color:#666;font-style:italic"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$BASE_URL&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;/&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$INTERVALS_UID&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;/activities?oldest=&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$OLDEST&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;&amp;amp;newest=&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$NEWEST&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#888;font-style:italic"&gt;# CSV header&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;font-style:italic"&gt;echo&lt;/span&gt; &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;date,cumulative_distance&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#888;font-style:italic"&gt;# Initialise cumulative distance and iterate through each date&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;cumulative_distance&lt;/span&gt;=0
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;current_date&lt;/span&gt;=&lt;span style="font-weight:bold;text-decoration:underline"&gt;$(&lt;/span&gt;date -I -d &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$OLDEST&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;end_date&lt;/span&gt;=&lt;span style="font-weight:bold;text-decoration:underline"&gt;$(&lt;/span&gt;date -I -d &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$NEWEST&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt; + 1 day&amp;#34;&lt;/span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;while&lt;/span&gt; [ &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$current_date&lt;/span&gt; != &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$end_date&lt;/span&gt; ]; &lt;span style="font-weight:bold;text-decoration:underline"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#888;font-style:italic"&gt;# Calculate total distance for the current day&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;day_distance&lt;/span&gt;=&lt;span style="font-weight:bold;text-decoration:underline"&gt;$(&lt;/span&gt;&lt;span style="font-weight:bold;font-style:italic"&gt;echo&lt;/span&gt; &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$activities&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt; | &lt;span style="color:#666;font-style:italic"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; jq --arg date &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$current_date&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#666;font-style:italic"&gt;&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt; map(select(.type == &amp;#34;Run&amp;#34; and 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt; (.start_date_local | startswith($date)))) | 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt; map(.distance) | 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt; add // 0&amp;#39;&lt;/span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;)&lt;/span&gt; &lt;span style="color:#888;font-style:italic"&gt;# return day distance (or return 0 if false or null)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#888;font-style:italic"&gt;# Add day distance to cumulative distance&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;cumulative_distance&lt;/span&gt;=&lt;span style="font-weight:bold;text-decoration:underline"&gt;$(&lt;/span&gt;&lt;span style="font-weight:bold;font-style:italic"&gt;echo&lt;/span&gt; &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;[&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$cumulative_distance&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;, &lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$day_distance&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;]&amp;#34;&lt;/span&gt; | jq &lt;span style="color:#666;font-style:italic"&gt;&amp;#39;add&amp;#39;&lt;/span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#888;font-style:italic"&gt;# Date and cumulative distance up until current date&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;echo&lt;/span&gt; &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$current_date&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;,&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$cumulative_distance&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#888;font-style:italic"&gt;# Move to the next day&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;current_date&lt;/span&gt;=&lt;span style="font-weight:bold;text-decoration:underline"&gt;$(&lt;/span&gt;date -I -d &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$current_date&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt; + 1 day&amp;#34;&lt;/span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csv" data-lang="csv"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt;date&lt;/span&gt;,&lt;span style="color:#666;font-style:italic"&gt;cumulative_distance&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt;2024-01-01&lt;/span&gt;,&lt;span style="color:#666;font-style:italic"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt;2024-01-02&lt;/span&gt;,&lt;span style="color:#666;font-style:italic"&gt;6919&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt;2024-01-03&lt;/span&gt;,&lt;span style="color:#666;font-style:italic"&gt;6919&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt;2024-01-04&lt;/span&gt;,&lt;span style="color:#666;font-style:italic"&gt;10034&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt;2024-01-05&lt;/span&gt;,&lt;span style="color:#666;font-style:italic"&gt;10034&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt;2024-12-27&lt;/span&gt;,&lt;span style="color:#666;font-style:italic"&gt;958647.54&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt;2024-12-28&lt;/span&gt;,&lt;span style="color:#666;font-style:italic"&gt;973656.54&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt;2024-12-29&lt;/span&gt;,&lt;span style="color:#666;font-style:italic"&gt;973656.54&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt;2024-12-30&lt;/span&gt;,&lt;span style="color:#666;font-style:italic"&gt;980075.54&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt;2024-12-31&lt;/span&gt;,&lt;span style="color:#666;font-style:italic"&gt;1000088.54&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.gnuplot.info/"&gt;gnuplot&lt;/a&gt;:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gnuplot" data-lang="gnuplot"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;set&lt;/span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;terminal&lt;/span&gt; pngcairo size 1024,768 font &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;iA Writer Quattro V&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;set&lt;/span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;output&lt;/span&gt; &lt;span style="color:#666;font-style:italic"&gt;&amp;#39;cumulative_distance_graph.png&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style=""&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#888;font-style:italic"&gt;# Set data file separator and time-related settings&lt;/span&gt;&lt;span style=""&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;set&lt;/span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;datafile&lt;/span&gt; separator &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;,&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;set&lt;/span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;xdata&lt;/span&gt; time
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;set&lt;/span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;timefmt&lt;/span&gt; &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;%Y-%m-%d&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;set&lt;/span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;format&lt;/span&gt; x &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;%B&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;set&lt;/span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;ylabel&lt;/span&gt; &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;Cumulative Running Distance in 2024&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;set&lt;/span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;grid&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style=""&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#888;font-style:italic"&gt;# Customize axis and range&lt;/span&gt;&lt;span style=""&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;set&lt;/span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;xtics&lt;/span&gt; rotate by -45
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;set&lt;/span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;yrange&lt;/span&gt; [0:1150]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;set&lt;/span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;xrange&lt;/span&gt; [&lt;span style="color:#666;font-style:italic"&gt;&amp;#39;2024-01-01&amp;#39;&lt;/span&gt;:*]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style=""&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#888;font-style:italic"&gt;# Set margins&lt;/span&gt;&lt;span style=""&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;set&lt;/span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;lmargin&lt;/span&gt; 16
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;set&lt;/span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;rmargin&lt;/span&gt; 10
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;set&lt;/span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;tmargin&lt;/span&gt; 5
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;set&lt;/span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;bmargin&lt;/span&gt; 6
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style=""&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#888;font-style:italic"&gt;# Mark specific races with arrows and labels&lt;/span&gt;&lt;span style=""&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;set&lt;/span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;arrow&lt;/span&gt; from &lt;span style="color:#666;font-style:italic"&gt;&amp;#39;2024-06-01&amp;#39;&lt;/span&gt;,0 to &lt;span style="color:#666;font-style:italic"&gt;&amp;#39;2024-06-01&amp;#39;&lt;/span&gt;,1150 nohead lw 1 dashtype 3 linecolor &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;gray30&amp;#34;&lt;/span&gt; &lt;span style="color:#888;font-style:italic"&gt;# Stockholm marathon&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;set&lt;/span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;label&lt;/span&gt; &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;🇸🇪&amp;#34;&lt;/span&gt; at &lt;span style="color:#666;font-style:italic"&gt;&amp;#39;2024-06-03&amp;#39;&lt;/span&gt;,950
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style=""&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;set&lt;/span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;arrow&lt;/span&gt; from &lt;span style="color:#666;font-style:italic"&gt;&amp;#39;2024-09-15&amp;#39;&lt;/span&gt;,0 to &lt;span style="color:#666;font-style:italic"&gt;&amp;#39;2024-09-15&amp;#39;&lt;/span&gt;,1150 nohead lw 1 dashtype 3 linecolor &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;gray30&amp;#34;&lt;/span&gt; &lt;span style="color:#888;font-style:italic"&gt;# In Flanders Fields marathon&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;set&lt;/span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;label&lt;/span&gt; &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;🇧🇪&amp;#34;&lt;/span&gt; at &lt;span style="color:#666;font-style:italic"&gt;&amp;#39;2024-09-17&amp;#39;&lt;/span&gt;,950
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style=""&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#888;font-style:italic"&gt;# Plot cumulative distance and 1000 km goal with markers and styles&lt;/span&gt;&lt;span style=""&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;plot&lt;/span&gt; &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;cumulative_distance.csv&amp;#34;&lt;/span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;using&lt;/span&gt; 1:(&lt;span style=""&gt;$&lt;/span&gt;2/1000) &lt;span style="font-weight:bold;font-style:italic"&gt;with&lt;/span&gt; lines &lt;span style="font-weight:bold;font-style:italic"&gt;title&lt;/span&gt; &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;Cumulative Distance (km)&amp;#34;&lt;/span&gt; lw 2 linecolor rgb &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;orange-red&amp;#34;&lt;/span&gt;, \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 0 &lt;span style="font-weight:bold;font-style:italic"&gt;with&lt;/span&gt; lines &lt;span style="font-weight:bold;font-style:italic"&gt;title&lt;/span&gt; &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;Marathons&amp;#34;&lt;/span&gt; lw 1 dashtype 3 linecolor &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;black&amp;#34;&lt;/span&gt;, \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 1000 &lt;span style="font-weight:bold;font-style:italic"&gt;with&lt;/span&gt; lines &lt;span style="font-weight:bold;font-style:italic"&gt;notitle&lt;/span&gt; &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;1000 km&amp;#34;&lt;/span&gt; lw 1 dashtype 2 linecolor &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;black&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Common Favourite Films on Letterboxd</title><link>http://patrick.vanderspie.gl/notes/2024-12-26/</link><pubDate>Thu, 26 Dec 2024 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/notes/2024-12-26/</guid><description>&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://letterboxd.com/pvdsp/"&gt;Letterboxd&lt;/a&gt; allows users to list up to four favourite films, but there&amp;rsquo;s no built-in way to find people with similar tastes. To solve this, I developed a script to scrape &amp;lsquo;fans&amp;rsquo; of specific films and identify overlapping favourites.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;










&lt;figure class=""&gt;

 &lt;div&gt;&lt;img loading="lazy" alt="My favourite films on Letterboxd" src=" /notes/20241225-favourites.png"&gt;&lt;/div&gt;

 
 
 &lt;div class="caption-container"&gt;
 &lt;figcaption&gt; My favourite films on Letterboxd &lt;/figcaption&gt;
 &lt;/div&gt;
 
 
&lt;/figure&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="scraping-fans"&gt;Scraping Fans&lt;/h2&gt;
&lt;p&gt;As there is no public Letterboxd API&lt;label for="sidenote-0" class="sidenote-number"&gt;&lt;/label&gt;&lt;input type="checkbox" id="sidenote-0" class="sidenote-toggle"&gt;&lt;span class="sidenote"&gt;I requested access to the Letterboxd API beta in 2016, but never received a response.&lt;/span&gt; but I still want to find people with similar movie tastes,
I wrote a script that takes a Letterboxd movie identifier as an argument and scrapes the list of users who have listed this movie as one of their four favourites (also called &amp;ldquo;fans&amp;rdquo; on Letterboxd).
This script &lt;code&gt;curl&lt;/code&gt;s every fan page of the given movie, extracting user identifiers through a regex with &lt;code&gt;grep&lt;/code&gt;, and appending them to a &lt;code&gt;CSV&lt;/code&gt; file.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#888;font-weight:bold"&gt;#!/bin/sh
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;movie&lt;/span&gt;=&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;page&lt;/span&gt;=1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;while&lt;/span&gt; :; &lt;span style="font-weight:bold;text-decoration:underline"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;fans&lt;/span&gt;=&lt;span style="font-weight:bold;text-decoration:underline"&gt;$(&lt;/span&gt;curl --silent &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;https://letterboxd.com/film/&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$movie&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;/fans/page/&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$page&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;/&amp;#34;&lt;/span&gt; | &lt;span style="color:#666;font-style:italic"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; grep -Po &lt;span style="color:#666;font-style:italic"&gt;&amp;#39;(?&amp;lt;=a href=&amp;#34;/)[^&amp;#34;]+(?=/\&amp;#34; class=\&amp;#34;name\&amp;#34;)&amp;#39;&lt;/span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [ -z &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$fans&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt; ] &amp;amp;&amp;amp; &lt;span style="font-weight:bold;font-style:italic"&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;echo&lt;/span&gt; &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$fans&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt; &amp;gt;&amp;gt; &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;${&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;movie&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;}&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;_fans.csv&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;page&lt;/span&gt;=&lt;span style="font-weight:bold;text-decoration:underline"&gt;$((&lt;/span&gt;page + 1&lt;span style="font-weight:bold;text-decoration:underline"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As a test, we can look at the &lt;a href="https://letterboxd.com/film/the-innocents-2021/"&gt;&amp;ldquo;The Innocents&amp;rdquo;&lt;/a&gt;, which currently has 88 fans.
&lt;code&gt;&amp;quot;./letterboxdFans.sh the-innocents-2021&amp;quot;&lt;/code&gt; produces a &lt;code&gt;CSV&lt;/code&gt; named &lt;code&gt;&amp;quot;the-innocents-2021_fans.csv&amp;quot;&lt;/code&gt; in the same folder.
Using the &lt;code&gt;fish&lt;/code&gt; shell, we check the number of entries by counting newlines in the &lt;code&gt;CSV&lt;/code&gt; with &lt;code&gt;cat&lt;/code&gt; and &lt;code&gt;count&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ cat the-innocents-2021_fans.csv | count
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;88
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Looking at some popular films (&lt;em&gt;like &lt;a href="https://letterboxd.com/film/parasite-2019/"&gt;Parasite&lt;/a&gt;, for example&lt;/em&gt;) shows that we can see at most 6.4k fans even though there are 102k of them in this specific case, however.
As there are 25 fans displayed per page, and we can only scrape 6.4k of them, this means that the fan pages are capped at page 256.
Manually confirming this indeed shows that there are at most &lt;a href="https://letterboxd.com/film/parasite-2019/fans/page/256/"&gt;256 pages&lt;/a&gt; of alphabetically ordered fans per film.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="finding-similar-profiles"&gt;Finding Similar Profiles&lt;/h2&gt;
&lt;p&gt;After scraping &lt;del&gt;all&lt;/del&gt; at most 6.4k fans of each of my four favourite films and putting the resulting &lt;code&gt;CSV&lt;/code&gt;s in a separate folder, we can find profiles that have at least two favourite films in common by looking for duplicate entries:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ ls letterboxd_fans/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;good-time_fans.csv 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;paterson_fans.csv 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;perfect-days-2023_fans.csv 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;uncut-gems_fans.csv
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ cat letterboxd_fans/* | sort &amp;gt; merged.csv
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ uniq -c merged.csv | sort -nr | head -n 5
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 2 mandypixel
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 2 malcolmconger
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 2 louistoth
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 2 loshmy
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 2 ln42
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="automatically-following-profiles"&gt;Automatically Following Profiles&lt;/h2&gt;
&lt;p&gt;I attempted to automatically follow profiles that share at least two favourite films using &lt;a href="https://www.selenium.dev/"&gt;Selenium&lt;/a&gt;, but only got as far as automatically visiting every profile with shared favourite films.&lt;/p&gt;
&lt;p&gt;Current issues include not being able to use an existing Firefox profile that is logged into my Letterboxd account to Selenium, and not being able to automatically click on the Follow button.&lt;/p&gt;
&lt;p&gt;As this is just a quick one-time project, I manually logged in using the browser that pops up after starting my script before automatically cycling through profiles from the &lt;code&gt;merged.csv&lt;/code&gt; list and manually clicking the follow button before the next profile page loads. This allowed me to quickly follow a couple of profiles with common favourite movies.&lt;/p&gt;</description></item><item><title>"Using AI to Detect the Unusual"</title><link>http://patrick.vanderspie.gl/posts/fari-2024/</link><pubDate>Mon, 25 Nov 2024 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/posts/fari-2024/</guid><description>&lt;blockquote&gt;
&lt;p&gt;This is an abbreviated transcript of my &lt;a href="https://www.fari.brussels/news-and-media-article/happy-hours"&gt;FARI &amp;ldquo;Happy Hour&amp;rdquo;&lt;/a&gt; talk titled &amp;ldquo;Using AI to Detect the Unusual&amp;rdquo;, held at BeCentral on the 25th of November, 2024. The slides I used during my talk can be found &lt;a href="http://patrick.vanderspie.gl/posts/fari-2024/slides.pdf"&gt;here&lt;/a&gt;. This transcript was created using &lt;a href="https://openai.com/index/whisper/"&gt;OpenAI&amp;rsquo;s Whisper model&lt;/a&gt; and edited using GPT-4o.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;










&lt;figure class=""&gt;

 &lt;div&gt;&lt;img loading="lazy" alt="" src=" /posts/fari-2024/presentation-photo.jpg"&gt;&lt;/div&gt;

 
 
 
&lt;/figure&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h1 id="introduction"&gt;Introduction&lt;/h1&gt;
&lt;p&gt;Tonight, I&amp;rsquo;m going to talk about how we can use artificial intelligence to detect the unusual. If I knew nothing about artificial intelligence, I would have three main questions regarding this title:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;What is artificial intelligence and how do we use it in general?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;What is the unusual, and how would we traditionally detect this without using artificial intelligence?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;How would we then use AI to detect the unusual?&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id="what-is-artificial-intelligence"&gt;What is Artificial Intelligence?&lt;/h1&gt;
&lt;p&gt;Artificial intelligence (AI) is a field of research. It is a subset of mathematics and computer science, and it overlaps with philosophy and linguistics, depending on the specific subset of AI being studied. This interdisciplinary nature makes it a fascinating field because you often collaborate with a diverse group of people across various domains.&lt;/p&gt;
&lt;p&gt;AI has been researched since the 1950s, and although we&amp;rsquo;ve heard a lot about it in media recently, the increase in computing power over the last few decades has enabled us to perform remarkable tasks based on the research conducted during this time.&lt;/p&gt;
&lt;h2 id="examples-of-ai-applications"&gt;Examples of AI Applications&lt;/h2&gt;
&lt;p&gt;I have some examples of how we use artificial intelligence:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Search:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In 1996, an AI algorithm named Deep Blue managed to beat the world chess champion, Garry Kasparov.&lt;/li&gt;
&lt;li&gt;More recently, AlphaGo competed against the second-best player in Go, a game with greater complexity than chess. For those who haven&amp;rsquo;t seen it, I recommend the excellent documentary about it.&lt;/li&gt;
&lt;li&gt;Day-to-day applications like Google Maps and Waze help you navigate from point A to point B in the most efficient way possible. You might not think of this as AI, but it results from extensive AI research.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Classification:&lt;/strong&gt; If you have a large dataset containing labeled images of cats and dogs, for instance, you can use AI to assign the correct label to new images as they come in. Google offers &amp;ldquo;teachable machines&amp;rdquo; that allows users to train classification models using their webcam, requiring no programming experience.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Generative AI:&lt;/strong&gt; Tools like ChatGPT for text generation and DALL-E for image generation have gained popularity recently. While impressive, it’s crucial to recognize that generative AI is not the only area of AI research. There are also significant studies in classification, search, and reinforcement learning, for example.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="what-ai-isnt"&gt;What AI Isn’t&lt;/h2&gt;
&lt;p&gt;Now that we&amp;rsquo;ve discussed what artificial intelligence is, it’s also important to clarify what AI isn’t.&lt;/p&gt;
&lt;p&gt;First, AI isn’t about creating conscious machines, a notion often propagated in science fiction. While artificial general intelligence—AI with capabilities akin to human intelligence—is a goal for some researchers, most focus on narrow AI tasks. When companies vaguely claim they &amp;ldquo;use an AI&amp;rdquo; for significant goals, it raises red flags.&lt;/p&gt;
&lt;p&gt;For example, it would be like a toothpaste manufacturer saying they used &amp;ldquo;a chemistry&amp;rdquo; to create better toothpaste—it doesn’t quite make sense. It’s important not to fall for the hype surrounding AI in the media. AI has nothing to do with Terminators or humanoid robots; it’s grounded in real-world applications.&lt;/p&gt;
&lt;h3 id="examples-of-ai-misuse"&gt;Examples of AI Misuse&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;ve put together some examples of how AI can be misused:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The &lt;em&gt;Smartschool&lt;/em&gt; Case:&lt;/strong&gt; &lt;em&gt;Smartschool&lt;/em&gt; is a platform where parents can communicate with their child&amp;rsquo;s teachers and access their test results. Recently, the company behind the platform announced plans to use AI to predict student dropout risks. This admirable goal (&lt;em&gt;trying to reduce student dropout&lt;/em&gt;) was poorly executed, essentially reducing these students to test results and vaguely implementing AI in their product without public dialogue, leading to significant backlash.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Social Media Companies:&lt;/strong&gt; Social media platforms are designed to maximize user engagement for profit through targeted advertisement. However, this focus can pose risks to younger users: vulnerable youth are presented with content that romanticizes self-harm, for example. Internal Facebook reports revealed that toxic content on Instagram negatively affects teenagers, but the company plays this down in public.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Dutch Child Care Benefit Scandal:&lt;/strong&gt; Thousands of families in the Netherlands were wrongly accused of fraud when applying for child care benefits, based on algorithmic predictions. This led to severe financial hardships for these families, illustrating how false positives can have disastrous impacts.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="detecting-the-unusual"&gt;Detecting the Unusual&lt;/h1&gt;
&lt;p&gt;Let’s now discuss the unusual and how we detect it.&lt;/p&gt;
&lt;h2 id="gathering-data"&gt;Gathering Data&lt;/h2&gt;
&lt;p&gt;Everything around us—every process, system, or activity—produces data, which we can collect through observation and measurement. Here are some examples:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Health Monitoring:&lt;/strong&gt; Tracking heart rate and blood pressure.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Financial Activity:&lt;/strong&gt; Every transaction you make with a credit card—transaction date, time, location, and amount.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Social Network Activity:&lt;/strong&gt; Actions like sending messages, making friend requests, and liking posts.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="understanding-anomalies"&gt;Understanding Anomalies&lt;/h2&gt;
&lt;p&gt;Anomalies are deviations from what we consider to be normal behavior, and these deviations leave traces in our observations. We are interested in understanding the underlying causes of these deviations. For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Health Monitoring:&lt;/strong&gt; An ECG can show if you have arrhythmia, indicating an underlying health issue.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Financial Activity:&lt;/strong&gt; If you generally conduct transactions in Belgium, an unexpected transaction from Nigeria would likely be labeled as anomalous.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Social Network Activity:&lt;/strong&gt; You can have spam messages or friend requests, also classifiable as anomalies.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="anomalies-vs-outliers"&gt;Anomalies vs. Outliers&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;s essential to distinguish between anomalies and outliers. Some sources claim they are the same, but this is misleading.&lt;/p&gt;
&lt;p&gt;Traditional examples of anomalies often show high peaks and obvious outliers in time series data. However, context matters significantly in determining whether a data point is an anomaly. For instance, a large peak in time series data could be normal if it occurs at regular intervals, suggesting that context is critical.&lt;/p&gt;
&lt;h1 id="using-ai-to-detect-the-unusual"&gt;Using AI to Detect the Unusual&lt;/h1&gt;
&lt;p&gt;Now that we&amp;rsquo;ve reached the point of understanding what anomalies are, we can discuss using AI for detecting these unusual patterns.&lt;/p&gt;
&lt;h2 id="anomaly-detection"&gt;Anomaly Detection&lt;/h2&gt;
&lt;p&gt;Anomaly detection refers to finding patterns in data that do not conform to expected behavior. The goal of identifying anomalies is to alert domain experts that something deviates from the norm and to provide actionable information to address the situation.&lt;/p&gt;
&lt;p&gt;For instance, in the medical field, detecting arrhythmia would alert healthcare professionals to investigate further.&lt;/p&gt;
&lt;h2 id="the-role-of-context"&gt;The Role of Context&lt;/h2&gt;
&lt;p&gt;Detecting anomalies is highly context-dependent. While classification involves labeling items, anomaly detection focuses on recognizing deviations from expected patterns—often rare occurrences.&lt;/p&gt;
&lt;p&gt;Traditional approaches to identifying anomalies are rule-based, which can be cumbersome and require constant updating. Relying solely on these rules may lead to missed anomalies or false triggers.&lt;/p&gt;
&lt;h2 id="a-rule-based-approach"&gt;A Rule-Based Approach&lt;/h2&gt;
&lt;p&gt;If we would have a manual rule-based configuration for anomaly detection:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Some anomalies would be missed if predefined rules do not trigger: no rule for certain anomalies means that these anomalies go undetected&lt;/li&gt;
&lt;li&gt;Rule-based trigger check on a “per event” basis, no “bigger picture”: context matters, and anomalies can involve multiple events&lt;/li&gt;
&lt;li&gt;Expert time would be wasted on hard-coded rule design instead of tackling the root cause of anomalies&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="challenges-in-anomaly-detection"&gt;Challenges in Anomaly Detection&lt;/h2&gt;
&lt;p&gt;In my research, I previously focused on developing a pattern-based series framework. Instead of relying on hard-coded rules, my framework allows us to apply various AI algorithms to learn a model of normal behavior and test new data against it. However, challenges exist, including:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Complexity of Normal Behavior:&lt;/strong&gt; Context and variation can make defining &amp;rsquo;normal&amp;rsquo; difficult.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Domain-Specific Definitions of Anomalies:&lt;/strong&gt; Definitions of anomalies can vary significantly depending on the domain (e.g., cybersecurity vs. healthcare).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ambiguity of Artifacts:&lt;/strong&gt; Different events might present similarly in data, making it challenging to differentiate between normal and anomalous behavior.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Impact of Mistakes:&lt;/strong&gt; Algorithms can produce both false positives and false negatives, leading to significant consequences.&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id="conclusion"&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;In summary:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;AI is a research field:&lt;/strong&gt; It focuses on narrow tasks and is not about conscious machines.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Anomaly detection aims to identify unusual patterns in various domains.&lt;/strong&gt; These patterns are often context-dependent deviations from what is deemed normal.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Algorithms can make mistakes,&lt;/strong&gt; resulting in false positives and negatives that can have disastrous consequences.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Thank you all for your attention. Slides and transcripts are available on my website. If you have any questions, please feel free to ask. Thank you!&lt;/p&gt;</description></item><item><title>"Hell's Hex Station" Write-Up</title><link>http://patrick.vanderspie.gl/posts/igctf-2024/</link><pubDate>Fri, 22 Nov 2024 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/posts/igctf-2024/</guid><description>&lt;blockquote&gt;
&lt;p&gt;In this write-up, I go over the step-by-step solution of &lt;strong&gt;&lt;em&gt;&amp;ldquo;Hell&amp;rsquo;s Hex Station&amp;rdquo;&lt;/em&gt;&lt;/strong&gt;, a challenge I created for the 2024 edition of &lt;a href="https://ctf.infogroep.be/"&gt;Infogroep&amp;rsquo;s Capture the Flag&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="description"&gt;Description&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Mein Fraulein,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;I haven&amp;#39;t heard from you in a while. Won&amp;#39;t you write me?
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;

&lt;audio class="player" controls preload="none"&gt;

&lt;source src="http://patrick.vanderspie.gl/posts/igctf-2024/recording.wav" type="audio/mp3"&gt;

&lt;/audio&gt;

&lt;/p&gt;
&lt;h2 id="solution"&gt;Solution&lt;/h2&gt;
&lt;p&gt;The title of the challenge is a reference to &lt;a href="https://en.wikipedia.org/wiki/Rudolf_Hell"&gt;Rudolf Hell&lt;/a&gt; (inventor of the &lt;em&gt;&amp;ldquo;Hellschreiber&amp;rdquo;&lt;/em&gt;), the &lt;a href="https://en.wikipedia.org/wiki/Hexadecimal"&gt;hexadecimal system&lt;/a&gt;, and &lt;a href="https://en.wikipedia.org/wiki/Numbers_station"&gt;numbers stations&lt;/a&gt;. The description is a reference to &lt;a href="https://youtu.be/OOxW4VNuHf0"&gt;a 2006 talk at DEF CON&lt;/a&gt; and also references the recurring German theme of this challenge&lt;label for="sidenote-1" class="sidenote-number"&gt;&lt;/label&gt;&lt;input type="checkbox" id="sidenote-1" class="sidenote-toggle"&gt;&lt;span class="sidenote"&gt;The &amp;ldquo;Mein Fraulein&amp;rdquo; description, Rudolf Hell being a German engineer, and the correct flag of this challenge containing a &lt;code&gt;ß&lt;/code&gt;.&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;The provided &lt;code&gt;.wav&lt;/code&gt; file starts with the tune of &lt;a href="https://en.wikipedia.org/wiki/Lincolnshire_Poacher_(numbers_station)"&gt;the &amp;ldquo;Lincolnshire Poacher&amp;rdquo; numbers station&lt;/a&gt; followed by a voice repeating &lt;code&gt;&amp;quot;CP437&amp;quot;&lt;/code&gt; and ends with beeping. Using &lt;code&gt;exiftool&lt;/code&gt; to look at the metadata of the audio file, we get the following output:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ exiftool recording.wav
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;⋯
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Comment : FELDHELL freq=14071.500
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Software : fldigi-4.1.06 (libsndfile-1.0.28)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;⋯
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;Comment&lt;/code&gt; and &lt;code&gt;Software&lt;/code&gt; values bring us to the solution of the challenge: the beeping that makes up the bulk of the &lt;code&gt;.wav&lt;/code&gt; file is &lt;a href="https://en.wikipedia.org/wiki/Hellschreiber"&gt;&amp;ldquo;Hellschreiber&amp;rdquo;&lt;/a&gt; in Feld Hell mode, a technique developed in 1927 by Rudolf Hell and currently in use by Ham radio hobbyists. Hellschreiber modes are based on character scanning&lt;label for="sidenote-2" class="sidenote-number"&gt;&lt;/label&gt;&lt;input type="checkbox" id="sidenote-2" class="sidenote-toggle"&gt;&lt;span class="sidenote"&gt;&lt;a href="http://www.w1hkj.com/modes/feld.htm"&gt;Feld Mode&lt;/a&gt;&lt;/span&gt;: we transmit characters as patterns of beeps, resembling a dot-matrix printer.&lt;/p&gt;
&lt;p&gt;As &lt;a href="https://en.wikipedia.org/wiki/Fldigi"&gt;&lt;code&gt;fldigi&lt;/code&gt;&lt;/a&gt; contains Feld Hell as one of their &lt;a href="https://en.wikipedia.org/wiki/Fldigi#Supported_digital_modes"&gt;supported digital modes&lt;/a&gt;, we can use it to decode the beeping in our file. After installing and opening &lt;code&gt;fldigi&lt;/code&gt;, we select the correct operational mode via &lt;code&gt;&amp;quot;Op Mode → Hell → Feld Hell&amp;quot;&lt;/code&gt; and load our &lt;code&gt;.wav&lt;/code&gt; file via &lt;code&gt;&amp;quot;File → Audio → Playback&amp;quot;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In the waterfall view on the bottom of the &lt;code&gt;fldigi&lt;/code&gt; window, we select the area that lights up when the beeping begins. Below, you can see a screenshot of the &lt;code&gt;fldigi&lt;/code&gt; program, around a minute after loading the &lt;code&gt;.wav&lt;/code&gt; file. A list of numbers in hexadecimal representation appear on screen:&lt;/p&gt;
&lt;p&gt;










&lt;figure class=""&gt;

 &lt;div&gt;&lt;img loading="lazy" alt="A screenshot of the fldigi program, a minute after loading the provided .wav file. A list of numbers appeared on the screen." src=" /posts/igctf-2024/fldigi.png"&gt;&lt;/div&gt;

 
 
 &lt;div class="caption-container"&gt;
 &lt;figcaption&gt; A screenshot of the &lt;code&gt;fldigi&lt;/code&gt; program, a minute after loading the provided &lt;code&gt;.wav&lt;/code&gt; file. A list of numbers appeared on the screen. &lt;/figcaption&gt;
 &lt;/div&gt;
 
 
&lt;/figure&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;49 47 43 54 46 7b 48 33 4c 4c e1 43 48 52 33 31 42 33 52 21 7d
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In general, we could use a range of different tools to transform this list of hexadecimal numbers to a string of characters. The simplest way of doing this would be through &lt;a href="https://gchq.github.io/CyberChef/"&gt;CyberChef&lt;/a&gt;. After giving our list of numbers as input, we can pick the &lt;code&gt;&amp;quot;From Hex&amp;quot;&lt;/code&gt; recipe (or choose &amp;ldquo;Magic&amp;rdquo; and provide &lt;code&gt;IGCTF&lt;/code&gt; as the crib) to obtain the following output:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;IGCTF{H3LLáCHR31B3R!}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is not the correct flag, however! The provided &lt;code&gt;.wav&lt;/code&gt; file specifically mentioned &lt;a href="https://en.wikipedia.org/wiki/Code_page_437"&gt;&lt;code&gt;&amp;quot;CP437&amp;quot;&lt;/code&gt;&lt;/a&gt;, which is a specific character encoding. Using Python (or any other tool that allows us to use &lt;code&gt;CP437&lt;/code&gt;), we obtain &lt;strong&gt;&lt;code&gt;IGCTF{H3LLßCHR31B3R!}&lt;/code&gt;&lt;/strong&gt;, which is the correct flag:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span style="font-weight:bold;font-style:italic"&gt;bytes&lt;/span&gt;.fromhex(hex_string).decode(&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;cp437&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt;&amp;#39;IGCTF{H3LLßCHR31B3R!}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Mindful use of LLMs</title><link>http://patrick.vanderspie.gl/posts/using-llms/</link><pubDate>Tue, 24 Sep 2024 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/posts/using-llms/</guid><description>&lt;p&gt;I believe large language models can bring value in use cases where they &lt;em&gt;assist&lt;/em&gt; with tasks like summarising, translating, and reformulating text. I have previously used these models for some quick translation work, and I also started using the OpenAI API to help me summarise the contents of my clipboard through &lt;a href="http://patrick.vanderspie.gl/notes/2024-09-09/"&gt;an Espanso shortcut&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Outside of summarising and translating texts, there are advantages for software developers as well. &lt;em&gt;GitHub Copilot&lt;/em&gt; drastically reduces the time needed to figure out popular APIs and successfully assists in writing proper documentation, for example. These tools could increase both the speed of development, codebase quality, and consistency as long as developers understand, reason about, and ultimately agree with every generated line of code and comment before committing their changes.&lt;/p&gt;
&lt;p&gt;I am also surprised about the quick adoption by a non-technical audience. LLMs would have seemed like magic to me only a couple of years ago, even though they are now commonplace—with friends and family members asking me to teach them &amp;ldquo;how to use ChatGPT&amp;rdquo; or enthusiastically telling me they already use it regularly. During a lightning talk on the risks of these models, for example, I asked the audience to raise their hands if they had already used ChatGPT in a professional setting. Almost everyone in the audience had done so recently.&lt;/p&gt;
&lt;h2 id="flip-side-of-the-coin"&gt;Flip side of the coin&lt;/h2&gt;
&lt;p&gt;Assistance with writing and coding aside, I believe there is also a serious flip side of the coin. &lt;strong&gt;Overreliance and excessive use of this technology could degrade writing proficiency and programming skills&lt;/strong&gt;. As &lt;a href="https://www.vrt.be/vrtnws/nl/2024/05/03/_schrijfkwaliteit-meten-kan-niet-meer-hoe-ai-onze-universiteite/"&gt;Belgian universities allow LLM usage by their students&lt;/a&gt;, we urgently need to reform how we evaluate the quality of a student&amp;rsquo;s work now that we can&amp;rsquo;t rely on traditional assignments. I&amp;rsquo;ve learned a lot by struggling through my university classes&amp;rsquo; programming projects, and I&amp;rsquo;m afraid I would have learned a lot less if I had easy access to software that completes my work for me.&lt;/p&gt;
&lt;p&gt;Next, it is easy to &lt;strong&gt;misuse these models&lt;/strong&gt; (&lt;em&gt;not always out of malice, but also out of misunderstanding how the technology works&lt;/em&gt;) — applying them to use cases that range from &lt;a href="https://mastodon.social/@jbaert/113155479457961565"&gt;wasteful but innocent&lt;/a&gt; to downright unethical and harmful. Consequences of this misuse include the &lt;a href="https://www.nytimes.com/2024/06/11/style/ai-search-slop.html"&gt;pollution of the internet with &lt;em&gt;slop&lt;/em&gt;&lt;/a&gt; and spreading misinformation (as some users do not realise that tools like ChatGPT are &lt;em&gt;not&lt;/em&gt; a replacement for search engines and should not be trusted to return reliable information). Sadly, because of these consequences, the whole field of AI is getting backlash—even though the field itself is so much more than just generative AI.&lt;/p&gt;
&lt;p&gt;As an example of unethical and harmful misuse, we have &lt;a href="https://zetane.com/ZetaForge-video-demo-voice.mp4"&gt;ZetaForge&lt;/a&gt;, a no-code tool to &amp;ldquo;rapidly build and deploy advanced AI pipelines&amp;rdquo;. The video linked above demonstrates how they use their tool to generate a textual description of war scenario images, on which they use a large language model to suggest a course of action to military personnel. In their own words, their demonstration pipeline &amp;ldquo;can be deployed as is, without any modification.&amp;rdquo; I&amp;rsquo;m not looking forward to a future where we rely on statistical models outputting &lt;span class="llm-generated"&gt;As a large language model, I recommend opening fire. 🔫🤠&lt;/span&gt; as a military strategy to ensure civilian safety.&lt;/p&gt;
&lt;p&gt;Finally, &lt;strong&gt;the resources necessary to keep these models operational:&lt;/strong&gt; a summary of a scientific paper — which I can perfectly write myself, albeit slower — is not worth the computing time, energy, and the &lt;a href="https://www.washingtonpost.com/technology/2024/09/18/energy-ai-use-electricity-water-data-centers/"&gt;bottle of water&lt;/a&gt; necessary to generate that summary. Combined with the fact that these models are trained on data without permission from artists and writers made me question my own use of these models in their current form.&lt;/p&gt;
&lt;h2 id="personal-ethics"&gt;Personal ethics&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;I have decided to stop using LLMs as a writing tool&lt;/strong&gt;, as — personally — their downsides outweigh the benefits. Summarising text was my initial use case for LLMs, but I summarise text to internalise and learn from the material I am working with. In my case, summarising should take time. LLMs promise speed, but speed isn&amp;rsquo;t always desired.&lt;/p&gt;
&lt;p&gt;I also previously used an LLM to help &lt;a href="http://patrick.vanderspie.gl/posts/automating-boggle/"&gt;write a blog post&lt;/a&gt; for a small half-day project. I still believe I used the tool responsibly, in this case, as I only used it to rephrase or expand certain lines of text, using the output as an initial draft and not copying generated text verbatim. I also clearly indicated which text was written with assistance, even though most was still my own. However, I plan to never use LLMs for writing blog posts again: I strongly believe that &lt;strong&gt;if I don&amp;rsquo;t take the time to write a text, no one should waste their time reading it either&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;I plan to put my money where my mouth is by taking the amount that I usually pay for API costs (which is only pennies, so I&amp;rsquo;m throwing in the price of a subscription to &lt;em&gt;ChatGPT Plus&lt;/em&gt;) and donating it to a charity standing up for nature and biodiversity in my region. I know I am not making a dent by donating a small amount of money to a charity and mindful use of LLMs, but I am doing my best to align my actions to my values.&lt;/p&gt;</description></item><item><title>llm + Espanso: Clipboard Summaries</title><link>http://patrick.vanderspie.gl/notes/2024-09-09/</link><pubDate>Mon, 09 Sep 2024 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/notes/2024-09-09/</guid><description>&lt;p&gt;I &lt;a href="http://patrick.vanderspie.gl/posts/obsidian-espanso-llm/"&gt;recently wrote an Espanso trigger&lt;/a&gt; named &lt;code&gt;:llm(⋯)&lt;/code&gt; that pipes the contents of my clipboard to &lt;a href="https://github.com/simonw/llm"&gt;Simon Willison&amp;rsquo;s &lt;code&gt;llm&lt;/code&gt; CLI tool&lt;/a&gt; and expands the trigger to &lt;code&gt;llm&lt;/code&gt;&amp;rsquo;s output in a custom Obsidian callout. This regex trigger expects a keyword (like &lt;code&gt;summarise&lt;/code&gt;, &lt;code&gt;simplify&lt;/code&gt;, or &lt;code&gt;translate&lt;/code&gt;) between its parenthesis, and transforms this keyword to a prompt that summarises, simplifies, or translates whatever text I current have within my clipboard.&lt;/p&gt;
&lt;p&gt;After frequent use of this trigger, I noticed that I mostly use &lt;code&gt;:llm(summarise)&lt;/code&gt;. To simplify my workflow, I decided to transfer summarisation to a dedicated &lt;code&gt;:summary&lt;/code&gt; trigger so that I don&amp;rsquo;t have to rely on providing and capturing keywords using regex:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- trigger: &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;:summary&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; replace: &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&amp;gt; [!llm] _\&amp;#34;{{title}}\&amp;#34;_\n&amp;gt; {{summary}}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; vars:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - name: clipboard
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; type: clipboard
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - name: summary
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; type: shell
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; params:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cmd: &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;echo $ESPANSO_CLIPBOARD | llm -m &amp;#39;gpt-4o&amp;#39; -s
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt; \ &amp;#39;Summarise the provided text into a concise UK English paragraph. 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt; \ Ensure the summary captures essential information.&amp;#39;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - name: title
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; type: shell
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; params:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cmd: &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;echo $ESPANSO_SUMMARY | llm -m &amp;#39;gpt-4o-mini&amp;#39; -s
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt; \ &amp;#39;Generate a short one-sentence title that accurately reflects
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt; \ the main idea of the summary. Use UK English.&amp;#39;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;










&lt;figure class=""&gt;

 &lt;div&gt;&lt;img loading="lazy" alt="" src=" /notes/20240909-llm-espanso.gif"&gt;&lt;/div&gt;

 
 
 
&lt;/figure&gt;&lt;/p&gt;</description></item><item><title>Notes from August</title><link>http://patrick.vanderspie.gl/posts/2024-08/</link><pubDate>Thu, 05 Sep 2024 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/posts/2024-08/</guid><description>&lt;p&gt;In August, after learning about the &lt;a href="https://indieweb.org/"&gt;IndieWeb&lt;/a&gt;, I updated my website and turned it into this blog. It has been years since I did something web-related, and I always enjoyed tinkering on the web, so I am glad I took the time to try and rebuild my website. This month was my first time using Hugo, customising an existing theme to fit my needs. I also:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://patrick.vanderspie.gl/notes/2024-08-07/"&gt;Automated the creation of daily notes on this blog using GitHub Actions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://patrick.vanderspie.gl/notes/2024-08-24/"&gt;Created category filters for this blog using the &lt;code&gt;:has&lt;/code&gt; selector in CSS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Pulled up-to-date statistics, like &lt;a href="http://patrick.vanderspie.gl/notes/2024-08-09/"&gt;distance ran in a year&lt;/a&gt; — &lt;em&gt;&lt;span class="tooltip"&gt;470.5 km&lt;span class="tooltiptext"&gt;Data pulled from intervals.icu&lt;/span&gt;&lt;/span&gt;&lt;/em&gt;, and &lt;a href="http://patrick.vanderspie.gl/notes/2024-08-17/"&gt;my current Tetra League ranking&lt;/a&gt; — &lt;em&gt;&lt;a href="https://ch.tetr.io/u/geuze/league"&gt;&lt;span&gt;10716.96 TR (&lt;img class="tr_rank" src="https://tetr.io/res/league-ranks/a.png"/&gt;)&lt;/span&gt;&lt;/a&gt;&lt;/em&gt;, using various APIs&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In terms of other small projects,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I &lt;a href="http://patrick.vanderspie.gl/notes/2024-08-10/"&gt;found new breakfast spots using Overture Places&lt;/a&gt; and &lt;code&gt;duckdb&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;Created a &lt;a href="http://patrick.vanderspie.gl/notes/2024-08-14/"&gt;Pomodoro timer script&lt;/a&gt; that keeps track of my work in Obsidian,&lt;/li&gt;
&lt;li&gt;Started &lt;a href="http://patrick.vanderspie.gl/notes/2024-08-21/"&gt;learning the Rust programming language&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;Looked into &lt;a href="http://patrick.vanderspie.gl/notes/2024-08-20/"&gt;visualising Belgian roads&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;Learned more about &lt;a href="http://patrick.vanderspie.gl/notes/2024-08-23/"&gt;&lt;code&gt;uv&lt;/code&gt; for Python&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="writing-daily-notes"&gt;Writing daily notes&lt;/h3&gt;
&lt;p&gt;Initially, &lt;a href="http://patrick.vanderspie.gl/posts/daily-notes/"&gt;I aimed to write a daily note on this blog&lt;/a&gt;, sharing small personal projects or interesting things I encountered that day. After twenty consecutive notes, however, I started putting quantity before quality on days I did not feel like writing. If I did not enjoy writing a note, I am sure it isn&amp;rsquo;t pleasant for others to read that note either. I am still looking for how and when to best write and share short notes for &lt;a href="https://www.jvt.me/posts/2017/06/25/blogumentation/"&gt;&amp;ldquo;blogumentation&amp;rdquo;&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="blogs-i-enjoyed-reading-this-august"&gt;Blogs I enjoyed reading this August&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://fabiensanglard.net/ilike/index.html"&gt;Fabien Sanglard&amp;rsquo;s &lt;code&gt;0X10 RULES&lt;/code&gt;&lt;/a&gt; are great rules to follow when creating (small) websites. On that note, I also appreciated &lt;a href="https://wonger.dev/posts/monospace-dump"&gt;Justin Wong&amp;rsquo;s collection of &amp;ldquo;monospace webpages&amp;rdquo;&lt;/a&gt;, &lt;a href="https://brutalist.report/?limit=5"&gt;The Brutalist Report&lt;/a&gt;, and &lt;a href="https://computer.rip/"&gt;computer.rip&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Other blogs that I added to my RSS feed this month include &lt;a href="https://simonwillison.net/"&gt;Simon Willison’s Weblog&lt;/a&gt;, &lt;a href="https://sebastiandedeyne.com/"&gt;Sebastian De Deyne&lt;/a&gt;, &lt;a href="https://matthodges.com/posts.html"&gt;Matt Hodges&lt;/a&gt;, &lt;a href="https://robinrendle.com/"&gt;Robin Rendle&lt;/a&gt;, &lt;a href="https://bradbarrish.com/"&gt;Brad Barrish&lt;/a&gt;, &lt;a href="https://anhvn.com/blog/"&gt;anhvn.com&lt;/a&gt;, and &lt;a href="https://jamesg.blog/"&gt;James G.&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Can GPT Boggle?</title><link>http://patrick.vanderspie.gl/notes/2024-08-27/</link><pubDate>Tue, 27 Aug 2024 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/notes/2024-08-27/</guid><description>&lt;p&gt;During the programming and writing of &lt;a href="http://patrick.vanderspie.gl/posts/automating-boggle"&gt;&amp;ldquo;Automating Boggle&amp;rdquo;&lt;/a&gt;, I remember being surprised that popular AI models (like GPT-4) — capable of many remarkable tasks — couldn&amp;rsquo;t do something so &amp;ldquo;trivial&amp;rdquo; as reading rotated dice. I regularly retry using the OpenAI API to recognise the labels on these dice, but the models always fail to do so (and they often fail spectacularly). The prompt I use is the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;#34;Given an image of a 4x4 grid of Boggle dice, extract and return the 16 letters from the grid, in a continuous string from top left to bottom right, left-to-right across each row. Account for any rotations of the letters. The output should be the correct sequence of letters as a continuous string, without any additional text, newlines, and formatting.&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It often happens that I get more than 16 letters in return, most of them not even present on the board. If we look at the OpenAI API documentation, under the section of &lt;a href="https://platform.openai.com/docs/guides/vision/limitations"&gt;&lt;em&gt;Limitations&lt;/em&gt;&lt;/a&gt;, we see:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Rotation:&lt;/strong&gt; The model may misinterpret rotated / upside-down text or images.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Instead of manually calling the API once in a while to see if an updated version of a vision model can complete the task, I plan to write a GitHub Actions workflow that regularly calls the API and compares the output to the expected solution, printing the results on this website. Guess this will be my AI model benchmark: how long before these models can read rotated dice from an image and the instructions from the prompt above?&lt;/p&gt;</description></item><item><title>git mailmap</title><link>http://patrick.vanderspie.gl/notes/2024-08-26/</link><pubDate>Mon, 26 Aug 2024 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/notes/2024-08-26/</guid><description>&lt;p&gt;I work on my Git repositories from different machines, which separates my contributions over different Git identities. Looking at &lt;a href="https://stackoverflow.com/a/9597462"&gt;all developers that contributed to one of my project&amp;rsquo;s repository&lt;/a&gt;, we get the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(base) pvdsp@laptop:~/git/⋯$ git shortlog -sne
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 71 Patrick Van der Spiegel &amp;lt;pvdsp@⋯.be&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 58 Patrick Van der Spiegel &amp;lt;patrick@⋯.com&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ⋯
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Adding a &lt;a href="https://git-scm.com/docs/gitmailmap"&gt;&lt;code&gt;.mailmap&lt;/code&gt; file&lt;/a&gt; to the root directory of the repository — following the &lt;code&gt;Proper Name &amp;lt;proper@email.xx&amp;gt; &amp;lt;commit@email.xx&amp;gt;&lt;/code&gt; structure — fixes this issue:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Patrick Van der Spiegel &amp;lt;pvdsp@⋯.be&amp;gt; &amp;lt;patrick@⋯.com&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(base) pvdsp@laptop:~/git/⋯$ git shortlog -sne
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 129 Patrick Van der Spiegel &amp;lt;pvdsp@⋯.be&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Joining Mastodon</title><link>http://patrick.vanderspie.gl/notes/2024-08-25/</link><pubDate>Sun, 25 Aug 2024 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/notes/2024-08-25/</guid><description>&lt;p&gt;After years of lurking on Twitter — barely contributing to conversations on the platform, and only using it to read tweets from creators I follow — I am trying out Mastodon for a while. I planned to do this a while ago: most people I follow on Twitter also use or cross-post to Mastodon, and it makes sense to use non-commercial alternatives where possible.&lt;/p&gt;
&lt;p&gt;Reading blog posts through my RSS reader is excellent for keeping up with news related to my interests, but I sometimes miss some interaction and discussion on these posts. I hope to find this interaction through Mastodon, as not every blog supports Webmentions (and I do not yet have it fully implemented either).&lt;/p&gt;
&lt;p&gt;For now, I have:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Manually searched and followed people of which I read their blogs&lt;/li&gt;
&lt;li&gt;Added a link to &lt;a href="https://c.im/@pvdsp"&gt;my Mastodon profile&lt;/a&gt; on my main page (&lt;a href="https://symbol.fediverse.info/"&gt;including ⁂&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Verified my domain by adding &lt;code&gt;&amp;lt;link href=&amp;quot;https://c.im/@pvdsp&amp;quot; rel=&amp;quot;me&amp;quot;&amp;gt;&lt;/code&gt; to the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; of my pages&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I looked into using &lt;a href="https://til.simonwillison.net/mastodon/custom-domain-mastodon"&gt;my custom domain for Mastodon&lt;/a&gt; so that I could use &lt;code&gt;@patrick@vanderspie.gl&lt;/code&gt; as my username, but I will postpone this as it involves setting up your own Mastodon server or using a &lt;a href="https://masto.host/"&gt;managed host&lt;/a&gt; (and I feel like using a custom domain is not worth yet another subscription).&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve heard good things about Mastodon so far, so I look forward to seeing if it is a better Twitter alternative!&lt;/p&gt;</description></item><item><title>CSS filter posts by category</title><link>http://patrick.vanderspie.gl/notes/2024-08-24/</link><pubDate>Sat, 24 Aug 2024 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/notes/2024-08-24/</guid><description>&lt;p&gt;As I also plan to upload non-technical posts and notes on my website, I added the ability to filter content based on categories. Trying to avoid another Javascript solution, I remembered the CSS &lt;code&gt;:has&lt;/code&gt; selector (which I read about in &lt;a href="https://ryanmulligan.dev/blog/we-can-has-it-all/"&gt;a blog post from Ryan Mulligan&amp;rsquo;s website&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;I based my solution on his examples, tailoring it to the classes available in my Hugo theme. First, I added a partial with a &lt;code&gt;fieldset&lt;/code&gt; and included it in the &lt;code&gt;HTML&lt;/code&gt; template used for lists. For now, the categories are hard-coded, as I don&amp;rsquo;t plan on adding more in the future:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;fieldset&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;legend&amp;gt;Filter by category:&amp;lt;/legend&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;div&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;input type=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;radio&amp;#34;&lt;/span&gt; id=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;all&amp;#34;&lt;/span&gt; name=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;filter&amp;#34;&lt;/span&gt; value=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;all&amp;#34;&lt;/span&gt; checked /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;label for=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;all&amp;#34;&lt;/span&gt;&amp;gt;Show all&amp;lt;/label&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/div&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;div&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;input type=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;radio&amp;#34;&lt;/span&gt; id=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;tech&amp;#34;&lt;/span&gt; name=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;filter&amp;#34;&lt;/span&gt; value=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;tech&amp;#34;&lt;/span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;label for=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;tech&amp;#34;&lt;/span&gt;&amp;gt;Only technical&amp;lt;/label&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/div&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;div&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;input type=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;radio&amp;#34;&lt;/span&gt; id=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;nontech&amp;#34;&lt;/span&gt; name=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;filter&amp;#34;&lt;/span&gt; value=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;nontech&amp;#34;&lt;/span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;label for=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;nontech&amp;#34;&lt;/span&gt;&amp;gt;Only non-technical&amp;lt;/label&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/div&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/fieldset&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next, I added the following to my &lt;code&gt;css&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;fieldset {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;text-decoration:underline"&gt;opacity&lt;/span&gt;: 75&lt;span style="font-weight:bold;text-decoration:underline"&gt;%&lt;/span&gt;; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;text-decoration:underline"&gt;font-size&lt;/span&gt;: 0.75&lt;span style="font-weight:bold;text-decoration:underline"&gt;em&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;text-decoration:underline"&gt;border&lt;/span&gt;: &lt;span style="font-weight:bold;text-decoration:underline"&gt;dotted&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;text-decoration:underline"&gt;border-width&lt;/span&gt;: 1&lt;span style="font-weight:bold;text-decoration:underline"&gt;px&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;body:has([name=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;filter&amp;#34;&lt;/span&gt;][value=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;tech&amp;#34;&lt;/span&gt;]:checked)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;post-line&lt;/span&gt;:not([category=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;tech&amp;#34;&lt;/span&gt;]) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;text-decoration:underline"&gt;display&lt;/span&gt;: &lt;span style="font-weight:bold;text-decoration:underline"&gt;none&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;body:has([name=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;filter&amp;#34;&lt;/span&gt;][value=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;nontech&amp;#34;&lt;/span&gt;]:checked)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;post-line&lt;/span&gt;:not([category=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;nontech&amp;#34;&lt;/span&gt;]) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;text-decoration:underline"&gt;display&lt;/span&gt;: &lt;span style="font-weight:bold;text-decoration:underline"&gt;none&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Finally, to make the filters work, I added a category to every post or note in Hugo:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-md" data-lang="md"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;title: &amp;#34;CSS filter posts by category&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;date: &amp;#34;2024-08-24&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;⋯
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;category: &amp;#34;tech&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and included this category in the partial for post entries:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;div class=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;post-line&amp;#34;&lt;/span&gt; category=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;{{ .Params.category }}&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	⋯
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/div&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Python packaging in Rust</title><link>http://patrick.vanderspie.gl/notes/2024-08-23/</link><pubDate>Fri, 23 Aug 2024 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/notes/2024-08-23/</guid><description>&lt;p&gt;Thanks to &lt;a href="https://simonwillison.net/2024/Aug/20/uv-unified-python-packaging/"&gt;a blog post by Simon Willison&lt;/a&gt;, I learned about the open-source Python tooling by &lt;a href="https://astral.sh/"&gt;Astral&lt;/a&gt;. Coincidentally, I started looking into the Rust programming language &lt;a href="http://patrick.vanderspie.gl/notes/2024-08-21/"&gt;a few days ago&lt;/a&gt; and was pleasantly surprised by Cargo.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;uv&lt;/code&gt; — which is a Python package and project manager written in Rust — is a kind of &lt;a href="https://astral.sh/blog/uv-unified-python-packaging"&gt;&amp;ldquo;Cargo, for Python&amp;rdquo;&lt;/a&gt;. Looking at the &lt;a href="https://github.com/astral-sh/uv?tab=readme-ov-file#highlights"&gt;highlights&lt;/a&gt; in &lt;code&gt;uv&lt;/code&gt;&amp;rsquo;s README.md file, the tool sounds promising, and I fully intend to try it out soon. The demonstrations on &lt;a href="https://astral.sh/blog/uv-unified-python-packaging"&gt;their blog post&lt;/a&gt; are convincing, especially &lt;code&gt;uvx&lt;/code&gt; and &lt;code&gt;uv run&lt;/code&gt;:&lt;/p&gt;
&lt;div class="quote-block"&gt;
 &lt;blockquote class="quote-content"&gt;With &lt;code&gt;uv run&lt;/code&gt;, you don&amp;rsquo;t have to think about activating virtual environments, managing dependencies, or keeping your project up-to-date. It just works.&lt;/blockquote&gt;
&lt;/div&gt;&lt;div class="quote-source-link"&gt;
 &lt;a href="https://astral.sh/blog/uv-unified-python-packaging" target="_blank" rel="noopener"&gt;Astral - uv: Unified Python packaging&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;and, more importantly:&lt;/p&gt;
&lt;div class="quote-block"&gt;
 &lt;blockquote class="quote-content"&gt;(⋯) it also adds features that are essential to local development but not covered by the standards, like relative paths and editable dependencies.&lt;/blockquote&gt;
&lt;/div&gt;&lt;div class="quote-source-link"&gt;
 &lt;a href="https://astral.sh/blog/uv-unified-python-packaging" target="_blank" rel="noopener"&gt;Astral - uv: Unified Python packaging&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Astral also provides a Python linter and code formatter written in Rust, named &lt;code&gt;ruff&lt;/code&gt;. I&amp;rsquo;m currently not using a dedicated linter; I&amp;rsquo;m just relying on my IDE and its built-in checks, but I might try adding &lt;code&gt;ruff&lt;/code&gt; to my workflow.&lt;/p&gt;</description></item><item><title>Tracking tasks in Obsidian</title><link>http://patrick.vanderspie.gl/notes/2024-08-22/</link><pubDate>Thu, 22 Aug 2024 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/notes/2024-08-22/</guid><description>&lt;p&gt;A couple of days ago, I made a simple addition to my &lt;a href="http://patrick.vanderspie.gl/notes/2024-08-14/"&gt;Pomodoro timer&lt;/a&gt;. To better keep track of work done in a given day, I edited my daily notes template of my Obsidian journal to include a table with a row for each pomodoro interval, explaining what I did during that interval:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-md" data-lang="md"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;type: research journal
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pomodori: 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# Tasks of the day
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;| Hours | Task |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;| ----- | ----- |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# Topics
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# Ideas and Insights
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I now keep track of when a new interval starts, and write a new row after each interval ends. This row includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The start and end time of the interval&lt;/li&gt;
&lt;li&gt;Space for a one-sentence summary of what I did during that interval&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;START_TIME&lt;/span&gt;=&lt;span style="font-weight:bold;text-decoration:underline"&gt;$(&lt;/span&gt;date +%H:%M&lt;span style="font-weight:bold;text-decoration:underline"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;ENTRY&lt;/span&gt;=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$JOURNAL&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;/&lt;/span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;$(&lt;/span&gt;date +%Y-%m-%d&lt;span style="font-weight:bold;text-decoration:underline"&gt;)&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt; Research Journal.md&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;⋯
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;NEW_ROW&lt;/span&gt;=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;| &lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$START_TIME&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt; — &lt;/span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;$(&lt;/span&gt;date +%H:%M&lt;span style="font-weight:bold;text-decoration:underline"&gt;)&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt; | ⋯ |&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sed -i &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;s/# Topics/&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$NEW_ROW&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;\n# Topics/&amp;#34;&lt;/span&gt; &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$ENTRY&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A short and quick addition, but I&amp;rsquo;ve noticed that it helps me keep focused on one specific task during each 25-minute interval, for now. As an example:&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Hours&lt;/th&gt;
					&lt;th&gt;Task&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;09:02 — 09:27&lt;/td&gt;
					&lt;td&gt;Literature review on &lt;code&gt;[[Complex Systems|DES]]&lt;/code&gt; &lt;code&gt;#phd&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;09:34 — 09:48&lt;/td&gt;
					&lt;td&gt;Reading &lt;code&gt;[[🔴 (Zimmermann, 2008)]]&lt;/code&gt; &lt;code&gt;#phd&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;10:48 — 11:16&lt;/td&gt;
					&lt;td&gt;Reading paper draft &lt;code&gt;#paper&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;⋯&lt;/td&gt;
					&lt;td&gt;⋯&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;</description></item><item><title>Learning Rust</title><link>http://patrick.vanderspie.gl/notes/2024-08-21/</link><pubDate>Wed, 21 Aug 2024 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/notes/2024-08-21/</guid><description>&lt;p&gt;I started experimenting with the Rust programming language by reading &lt;a href="https://doc.rust-lang.org/book/"&gt;&amp;ldquo;the book&amp;rdquo;&lt;/a&gt;, trying some basic things and loosely following along with the examples. Although I&amp;rsquo;ve only gone through the first three chapters — stopping after the common programming concepts and leaving the idea of ownership for later — I&amp;rsquo;m still planning to write down what I found interesting about the language compared to the ones I use more often (mainly Python and Julia).&lt;/p&gt;
&lt;p&gt;Nothing interesting will be written here for anyone familiar with Rust, but I&amp;rsquo;m growing fond of the idea behind &lt;a href="https://www.jvt.me/posts/2017/06/25/blogumentation/"&gt;&amp;ldquo;blogumentation&amp;rdquo;&lt;/a&gt; for self-documentation. In this case, writing things down that I found interesting will help me remember them:&lt;/p&gt;
&lt;h3 id="terminating-statements-with"&gt;&lt;strong&gt;Terminating statements with &lt;code&gt;;&lt;/code&gt;&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Like multiple other languages, Rust uses the semicolon after statements. I wondered why this is so often the convention, and found &lt;a href="https://ntietz.com/blog/researching-why-we-use-semicolons-as-statement-terminators/"&gt;a blog post by Nicole Tietz&lt;/a&gt; speculating why that is the case.&lt;/p&gt;
&lt;h3 id="cargo-and-initialising-git-repositories"&gt;Cargo and initialising Git repositories&lt;/h3&gt;
&lt;p&gt;Using Cargo — which also initialises a new Git repository by default and creates the project structure when you begin a new project — seems like a great workflow.&lt;/p&gt;
&lt;div class="quote-block"&gt;
 &lt;blockquote class="quote-content"&gt;Cargo expects your source files to live inside the &lt;code&gt;src&lt;/code&gt; directory. The top-level project directory is just for README files, license information, configuration files, and anything else not related to your code. Using Cargo helps you organise your projects. There&amp;rsquo;s a place for everything, and everything is in its place.&lt;/blockquote&gt;
&lt;/div&gt;&lt;div class="quote-source-link"&gt;
 &lt;a href="https://doc.rust-lang.org/book/ch01-03-hello-cargo.html" target="_blank" rel="noopener"&gt;The Rust Programming Language&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;In general, I think it&amp;rsquo;s helpful that it initialises and enforces this organisation. I tend to ignore conventions when quickly whipping something up in Python, which gets messy quickly.&lt;/p&gt;
&lt;h3 id="shadowing-of-immutable-variables"&gt;Shadowing of immutable variables&lt;/h3&gt;
&lt;p&gt;Variables are immutable by default, but I was initially confused as to why you would allow shadowing for immutable variables. I did not immediately see any scenario where it would make sense to shadow an immutable variable. This will probably make more sense once I see some examples in practice. Another thing about shadowing that I found a bit weird is the example below:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-rust" data-lang="rust"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;font-style:italic;text-decoration:underline"&gt;let&lt;/span&gt; spaces = &lt;span style="color:#666;font-style:italic"&gt;&amp;#34; &amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;font-style:italic;text-decoration:underline"&gt;let&lt;/span&gt; spaces = spaces.len();
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="quote-block"&gt;
 &lt;blockquote class="quote-content"&gt;The first spaces variable is a string type and the second spaces variable is a number type. Shadowing thus spares us from having to come up with different names, such as &lt;code&gt;spaces_str&lt;/code&gt; and &lt;code&gt;spaces_num&lt;/code&gt;; instead, we can reuse the simpler &lt;code&gt;spaces&lt;/code&gt; name.&lt;/blockquote&gt;
&lt;/div&gt;&lt;div class="quote-source-link"&gt;
 &lt;a href="https://doc.rust-lang.org/book/ch03-01-variables-and-mutability.html" target="_blank" rel="noopener"&gt;The Rust Programming Language&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;This feels like a fast way for things to get messy, shadowing the same variable in different scopes but changing the type (and thus the meaning) of the variable, but keeping the name. &lt;code&gt;spaces_str&lt;/code&gt; and &lt;code&gt;spaces_num&lt;/code&gt; don&amp;rsquo;t sound so bad to me, as the names at least convey meaning.&lt;/p&gt;
&lt;h3 id="visual-separator-for-integer-literals"&gt;Visual separator for integer literals&lt;/h3&gt;
&lt;div class="quote-block"&gt;
 &lt;blockquote class="quote-content"&gt;Number literals can also use _ as a visual separator to make the number easier to read, such as 1_000, which will have the same value as if you had specified 1000.&lt;/blockquote&gt;
&lt;/div&gt;&lt;div class="quote-source-link"&gt;
 &lt;a href="https://doc.rust-lang.org/book/ch03-02-data-types.html" target="_blank" rel="noopener"&gt;The Rust Programming Language&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Through looking up other languages that provide a visual separator for integer literals, I stumbled upon &lt;a href="https://github.com/ziglang/zig/issues/504"&gt;this GitHub issue&lt;/a&gt;, which contains some interesting discussion on separators.&lt;/p&gt;
&lt;h3 id="other-things-that-i-like-so-far-at-first-glance"&gt;Other things that I like so far, at first glance&lt;/h3&gt;
&lt;p&gt;A lot of these might seem very standard, but as Python is my daily driver, it&amp;rsquo;s nice to try a language that has:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Integer division truncating toward zero to the nearest integer:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-rust" data-lang="rust"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;font-style:italic;text-decoration:underline"&gt;let&lt;/span&gt; truncated = -5 / 3; &lt;span style="color:#888;font-style:italic"&gt;// Results in -1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;The terminology &amp;ldquo;destructuring&amp;rdquo; for breaking up a single tuple into parts (&lt;em&gt;which Python also has, but first time that I encounter this terminology&lt;/em&gt;):&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-rust" data-lang="rust"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;font-style:italic;text-decoration:underline"&gt;let&lt;/span&gt; tup = (500, 6.4, 1);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;font-style:italic;text-decoration:underline"&gt;let&lt;/span&gt; (x, y, z) = tup;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;The distinction between arrays and vectors, and the initialisation of an array using this notation:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-rust" data-lang="rust"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;font-style:italic;text-decoration:underline"&gt;let&lt;/span&gt; a = [3; 5]; &lt;span style="color:#888;font-style:italic"&gt;// same as writing let a = [3, 3, 3, 3, 3];
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;The fact that you must declare the type of each parameter in function signatures:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-rust" data-lang="rust"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;fn&lt;/span&gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print_labeled_measurement(5, &lt;span style="color:#666;font-style:italic"&gt;&amp;#39;h&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;fn&lt;/span&gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;print_labeled_measurement&lt;/span&gt;(value: &lt;span style="font-weight:bold;text-decoration:underline"&gt;i32&lt;/span&gt;, unit_label: &lt;span style="font-weight:bold;text-decoration:underline"&gt;char&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;println!&lt;/span&gt;(&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;The measurement is: &lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;{value}{unit_label}&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;The distinction between &lt;em&gt;acting&lt;/em&gt; and &lt;em&gt;returning&lt;/em&gt; through statements and expressions (and that expressions don&amp;rsquo;t have ending semicolons). I already see myself making mistakes by turning expressions into statements — not letting it return a value — by accidentally adding a semicolon. Luckily, the thrown errors are very readable, so far:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-rust" data-lang="rust"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#888;font-weight:bold"&gt;$&lt;/span&gt; cargo run
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Compiling functions v0.1.0 (file:&lt;span style="color:#666;font-style:italic"&gt;///projects/functions)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;error: &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;expected&lt;/span&gt; expression, found &lt;span style=""&gt;`&lt;/span&gt;&lt;span style="font-weight:bold;font-style:italic;text-decoration:underline"&gt;let&lt;/span&gt;&lt;span style=""&gt;`&lt;/span&gt; statement
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --&amp;gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;src&lt;/span&gt;/main.rs:2:14
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2 | &lt;span style="font-weight:bold;font-style:italic;text-decoration:underline"&gt;let&lt;/span&gt; x = (&lt;span style="font-weight:bold;font-style:italic;text-decoration:underline"&gt;let&lt;/span&gt; y = 6);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; | ^^^
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; = note: &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;only&lt;/span&gt; supported directly &lt;span style="font-weight:bold;text-decoration:underline"&gt;in&lt;/span&gt; conditions of &lt;span style=""&gt;`&lt;/span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;if&lt;/span&gt;&lt;span style=""&gt;`&lt;/span&gt; and &lt;span style=""&gt;`&lt;/span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;while&lt;/span&gt;&lt;span style=""&gt;`&lt;/span&gt; expressions
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;The fact that conditions must explicitly be booleans:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-rust" data-lang="rust"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#888;font-weight:bold"&gt;$&lt;/span&gt; cargo run
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Compiling branches v0.1.0 (file:&lt;span style="color:#666;font-style:italic"&gt;///projects/branches)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;error[E0308]: &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;mismatched&lt;/span&gt; types
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --&amp;gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;src&lt;/span&gt;/main.rs:4:8
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;4 | &lt;span style="font-weight:bold;text-decoration:underline"&gt;if&lt;/span&gt; number {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; | ^^^^^^ expected &lt;span style=""&gt;`&lt;/span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;bool&lt;/span&gt;&lt;span style=""&gt;`&lt;/span&gt;, found integer
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;For more information about this error, &lt;span style="font-weight:bold;text-decoration:underline"&gt;try&lt;/span&gt; &lt;span style=""&gt;`&lt;/span&gt;rustc --explain E0308&lt;span style=""&gt;`&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;error: &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;could&lt;/span&gt; not compile &lt;span style=""&gt;`&lt;/span&gt;branches&lt;span style=""&gt;`&lt;/span&gt; (bin &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;branches&amp;#34;&lt;/span&gt;) due to 1 previous error
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;One-line assignment using &lt;code&gt;if&lt;/code&gt;, but enforcing that the result of each arm must be of the same type:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-rust" data-lang="rust"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;font-style:italic;text-decoration:underline"&gt;let&lt;/span&gt; number = &lt;span style="font-weight:bold;text-decoration:underline"&gt;if&lt;/span&gt; condition { 5 } &lt;span style="font-weight:bold;text-decoration:underline"&gt;else&lt;/span&gt; { 6 };
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;loop&lt;/code&gt; keyword and loop labels (probably used sparingly as there are &lt;code&gt;while&lt;/code&gt; and &lt;code&gt;for&lt;/code&gt; keywords as well):&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-rust" data-lang="rust"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;fn&lt;/span&gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;text-decoration:underline"&gt;loop&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;println!&lt;/span&gt;(&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;again!&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Looking forward to learning more about Rust!&lt;/p&gt;</description></item><item><title>Visualising Belgian roads</title><link>http://patrick.vanderspie.gl/notes/2024-08-20/</link><pubDate>Tue, 20 Aug 2024 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/notes/2024-08-20/</guid><description>&lt;p&gt;&lt;figure class="dark"&gt;&lt;img src="http://patrick.vanderspie.gl/notes/belgium_roads_dark.png"
			alt="Visualisation of all roads in Belgium using city-roads"&gt;
&lt;/figure&gt;

&lt;figure class="light"&gt;&lt;img src="http://patrick.vanderspie.gl/notes/belgium_roads_light.png"
			alt="Visualisation of all roads in Belgium using city-roads"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;When exploring &lt;a href="http://patrick.vanderspie.gl/notes/2024-08-10/"&gt;Overture data&lt;/a&gt; earlier this month, I stumbled upon &lt;a href="https://benfry.com/allstreets/"&gt;&lt;em&gt;&amp;ldquo;All Streets&amp;rdquo;&lt;/em&gt; by Ben Fry&lt;/a&gt;. I loved the visualisation and wondered how I could reproduce it for other countries. Looking at Ben Fry&amp;rsquo;s writing archive, he briefly discussed his work in a &lt;a href="https://benfry.com/writing/archives/54/"&gt;blog post&lt;/a&gt; from 2008:&lt;/p&gt;
&lt;div class="quote-block"&gt;
 &lt;blockquote class="quote-content"&gt;Nothing particularly genius about this piece—it&amp;rsquo;s mostly just a matter of collecting the data and creating the image. But it&amp;rsquo;s one of those cases where even in a (relatively) raw format, the data itself is quite striking.&lt;/blockquote&gt;
&lt;/div&gt;&lt;div class="quote-source-link"&gt;
 &lt;a href="https://benfry.com/writing/archives/54/" target="_blank" rel="noopener"&gt;Ben Fry&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;&amp;ldquo;Collecting the data and creating the image&amp;rdquo;: as easy as &lt;a href="https://knowyourmeme.com/memes/how-to-draw-an-owl"&gt;drawing an owl&lt;/a&gt;. Luckily, the rest of the blog post reveals a bit more of the process — but sadly doesn&amp;rsquo;t really help me in reproducing it for other countries.&lt;/p&gt;
&lt;p&gt;After a bit of Googling, I found great work by &lt;a href="https://github.com/anvaka"&gt;Andrei Kashcha&lt;/a&gt;: &lt;a href="https://anvaka.github.io/city-roads/"&gt;&lt;code&gt;city-roads&lt;/code&gt;&lt;/a&gt;, which allows you to render roads in any area using data from OpenStreetMap, which I used for the image at the top of this note. I plan to dive into &lt;a href="https://github.com/anvaka/city-roads"&gt;the open-sourced code&lt;/a&gt; of &lt;code&gt;city-roads&lt;/code&gt;, and I might try to make something similar from scratch using Overture (just to learn how it works, as inspired by &lt;a href="https://lobste.rs/s/wimfh5/you_should_make_new_programming_language#c_zhzowj"&gt;a comment on lobste.rs&lt;/a&gt;):&lt;/p&gt;
&lt;div class="quote-block"&gt;
 &lt;blockquote class="quote-content"&gt;You should make a toy version of every major tool you use, if you can find the time and energy to do so. It&amp;rsquo;s a great way to understand the constraints that go into the tools you use and the limits of their capabilities.&lt;/blockquote&gt;
&lt;/div&gt;&lt;div class="quote-source-link"&gt;
 &lt;a href="https://lobste.rs/s/wimfh5/you_should_make_new_programming_language#c_zhzowj" target="_blank" rel="noopener"&gt;lobste.rs comment&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;I want to do something similar as &lt;code&gt;city-roads&lt;/code&gt;, but expand it by combining it with &lt;a href="https://docs.overturemaps.org/guides/places/"&gt;Overture Places data&lt;/a&gt;. Possibilities for visualisation include heatmaps for distance from road segments to specific types of places (like the nearest train station or bus stop, for example), or create a &lt;a href="https://www.chronotrains.com"&gt;Chronotrains&lt;/a&gt;-style alternative on a Belgian map, using open data from NMBS, &lt;a href="https://data.delijn.be/"&gt;De Lijn&lt;/a&gt;, and &lt;a href="https://www.letec.be/"&gt;TEC&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Displaying tags in Hugo</title><link>http://patrick.vanderspie.gl/notes/2024-08-19/</link><pubDate>Mon, 19 Aug 2024 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/notes/2024-08-19/</guid><description>&lt;p&gt;As I plan to write about a variety of different topics on this website, I decided to add tags to the properties of all my posts and notes so far:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-md" data-lang="md"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;title: &amp;#34;Displaying tags in Hugo&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;date: &amp;#34;2024-08-19&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tags: [&amp;#34;hugo&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;⋯
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Tags were already available in the &lt;a href="https://github.com/tomfran/typo"&gt;Hugo theme&lt;/a&gt; that I am currently using, but I did not like the way they were displayed. I edited &lt;code&gt;partials/post-entry.html&lt;/code&gt; so there&amp;rsquo;s a loop over every tag of a post, displaying them as a comma-delimited list next to the post or note&amp;rsquo;s title:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;div class=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;post-line&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {{ $dateFormat := &amp;#34;2 Jan 2006&amp;#34;}}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {{ with .Site.Params.listDateFormat }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {{ $dateFormat = .}}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {{ end }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;p class=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;line-date&amp;#34;&lt;/span&gt;&amp;gt;{{ .Date.Format $dateFormat }} &amp;lt;/p&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;span&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;a href=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;{{ .RelPermalink }}&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {{- .Title -}}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/a&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {{ if .Site.Params.listSummaries }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;span class=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;post-tags&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {{- range $index, $tag := .Params.tags -}}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {{ if $index }}, {{ end }}&amp;lt;a href=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;{{ printf &amp;#34;&lt;/span&gt;&lt;span style=""&gt;/&lt;/span&gt;tags&lt;span style=""&gt;/%&lt;/span&gt;s&lt;span style=""&gt;/&amp;#34;&lt;/span&gt; &lt;span style=""&gt;$&lt;/span&gt;tag &lt;span style=""&gt;|&lt;/span&gt; urlize &lt;span style=""&gt;}}&amp;#34;&lt;/span&gt;&amp;gt;#{{ $tag }}&amp;lt;/a&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {{- end -}}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/span&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;div class=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;line-summary&amp;#34;&lt;/span&gt;&amp;gt; {{ .Description | markdownify }} &amp;lt;/div&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {{ end }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/span&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/div&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;post-tags&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;text-decoration:underline"&gt;font-size&lt;/span&gt;: 0.7&lt;span style="font-weight:bold;text-decoration:underline"&gt;em&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;text-decoration:underline"&gt;opacity&lt;/span&gt;: 50&lt;span style="font-weight:bold;text-decoration:underline"&gt;%&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;text-decoration:underline"&gt;vertical-align&lt;/span&gt;: &lt;span style="font-weight:bold;text-decoration:underline"&gt;baseline&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Clicking on the link of the tag brings you to a list of all posts or note&amp;rsquo;s with the same tag.&lt;/p&gt;</description></item><item><title>Using data sources in Hugo</title><link>http://patrick.vanderspie.gl/notes/2024-08-18/</link><pubDate>Sun, 18 Aug 2024 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/notes/2024-08-18/</guid><description>&lt;p&gt;Until now, I have been storing different variables as site parameters in my Hugo website&amp;rsquo;s &lt;code&gt;hugo.toml&lt;/code&gt; file. A regularly triggered GitHub Actions workflow updates these variables by using various APIs to check for any changes. If changes are detected, the workflow updates the &lt;code&gt;hugo.toml&lt;/code&gt; file with the new values (replacing the old ones using &lt;code&gt;sed&lt;/code&gt;) and pushes the changes to my website’s GitHub repository. There, another GitHub Workflow builds my Hugo website and deploys it to GitHub Pages.&lt;/p&gt;
&lt;p&gt;As I start tracking more variables than originally planned, it makes sense to store them the proper way: using &lt;a href="https://gohugo.io/content-management/data-sources/"&gt;data sources&lt;/a&gt; in Hugo. My plan is to keep a &lt;code&gt;yaml&lt;/code&gt; file in my Hugo website&amp;rsquo;s data directory, which will store all variables that I want to display on my website. The rest of the workflow should remain unchanged, but this approach should separate these variables from actual site parameters.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;running_distance: 720851.2999999999
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;running_cp: 3.5694862545565007
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;writing_streak: 12
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;best_writing_streak: 12
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;best_writing_streak_date: &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;2024-08-19&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tr_value: 6150.468645723648
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tr_rank: b
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;m planning to write a decent and complete &lt;a href="http://patrick.vanderspie.gl/posts/"&gt;post&lt;/a&gt; explaining which APIs I use, the variables that I store (and plan to store in the future), and how these GitHub Workflows work. I currently keep track of the following variables:&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Variable&lt;/th&gt;
					&lt;th&gt;Value&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Longest writing streak&lt;/td&gt;
					&lt;td&gt;




20 days | Achieved on 27 Aug 2024&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Current writing streak&lt;/td&gt;
					&lt;td&gt;



0 days | Updated on 12 Aug 2026&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Running Critical Power&lt;/td&gt;
					&lt;td&gt;3.490 W/kg&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Distance ran this year&lt;/td&gt;
					&lt;td&gt;470.5 km&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;TETR.IO&amp;rsquo;s TETRA LEAGUE&lt;/td&gt;
					&lt;td&gt;&lt;a href="https://ch.tetr.io/u/geuze/league"&gt;&lt;span&gt;10716.96 TR (&lt;img class="tr_rank" src="https://tetr.io/res/league-ranks/a.png"/&gt;)&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;</description></item><item><title>Displaying TETR.IO TR on website</title><link>http://patrick.vanderspie.gl/notes/2024-08-17/</link><pubDate>Sat, 17 Aug 2024 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/notes/2024-08-17/</guid><description>&lt;p&gt;TETR.IO&amp;rsquo;s started its new season yesterday. &lt;a href="http://patrick.vanderspie.gl/notes/2024-08-13/"&gt;A couple of days ago, I planned to scrape my TETR.IO profile to display the change in my TR over time&lt;/a&gt;. The game&amp;rsquo;s &lt;a href="https://tetr.io/about/patchnotes/#chlog_BETA_1_2_0"&gt;patch notes&lt;/a&gt; include the feature that I was missing in the game&amp;rsquo;s previous season, however:&lt;/p&gt;
&lt;div class="quote-block"&gt;
 &lt;blockquote class="quote-content"&gt;You can now see your TR change over time on the TETRA CHANNEL site.&lt;/blockquote&gt;
&lt;/div&gt;&lt;div class="quote-source-link"&gt;
 &lt;a href="https://tetr.io/about/patchnotes/#chlog_BETA_1_2_0" target="_blank" rel="noopener"&gt;TETR.IO Patch Notes&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Additionally, if I still want to include my TR over time on my website, scraping isn&amp;rsquo;t necessary at all: the patch notes mention that the game &lt;a href="https://tetr.io/about/api/"&gt;provides an API&lt;/a&gt;. Simply using &lt;code&gt;curl&lt;/code&gt; and &lt;code&gt;jq&lt;/code&gt; gives me all the data I need:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl https://ch.tetr.io/api/users/geuze/summaries/league | jq &lt;span style="color:#666;font-style:italic"&gt;&amp;#39;.data | .tr&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I store this data as a site parameter in my &lt;code&gt;hugo.toml&lt;/code&gt; file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;TETRIO_TR = 3090.2731291544947
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;TETRIO_RANK = &amp;#34;c+&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, I can use it in a Hugo shortcode:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;span&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	{{ printf &amp;#34;%.2f&amp;#34; .Site.Params.TETRIO_TR }} TR
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	(&amp;lt;img class=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;tr_rank&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		 src=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;https://tetr.io/res/league-ranks/{{ .Site.Params.TETRIO_RANK }}.png&amp;#34;&lt;/span&gt; /&amp;gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/span&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Which looks like this: &lt;strong&gt;&lt;a href="https://ch.tetr.io/u/geuze/league"&gt;&lt;span&gt;10716.96 TR (&lt;img class="tr_rank" src="https://tetr.io/res/league-ranks/a.png"/&gt;)&lt;/span&gt;&lt;/a&gt;&lt;/strong&gt;.
To keep this value up-to-date, I add it to a GitHub Actions workflow that uses the game&amp;rsquo;s API to retrieve my TR and rank, and replaces the current value in the &lt;code&gt;hugo.toml&lt;/code&gt; file using &lt;code&gt;sed&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Visualising multi-sport events</title><link>http://patrick.vanderspie.gl/notes/2024-08-16/</link><pubDate>Fri, 16 Aug 2024 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/notes/2024-08-16/</guid><description>&lt;p&gt;Today, I participated in my first duathlon — 5 kilometres of running, followed by 32 kilometres of cycling, and finishing with another 5 kilometres of running:&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;&lt;/th&gt;
					&lt;th&gt;&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Run #1&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;00:24:54&lt;/strong&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;⋮ &lt;em&gt;Transition #1&lt;/em&gt;&lt;/td&gt;
					&lt;td&gt;&lt;em&gt;00:01:06&lt;/em&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Bike&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;01:21:49&lt;/strong&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;⋮ &lt;em&gt;Transition #2&lt;/em&gt;&lt;/td&gt;
					&lt;td&gt;&lt;em&gt;00:01:53&lt;/em&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Run #2&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;00:23:44&lt;/strong&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;⋮ &lt;em&gt;Total&lt;/em&gt;&lt;/td&gt;
					&lt;td&gt;&lt;em&gt;02:13:28&lt;/em&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;As I do with my separate running or cycling sessions, I record my performance (&lt;em&gt;HR, power output, pace&lt;/em&gt;) and upload it to Strava and &lt;a href="https://intervals.icu"&gt;intervals.icu&lt;/a&gt;. &lt;strong&gt;It surprises me, however, that there is no clear way of combining these separate activities into one multi-sport event.&lt;/strong&gt; I assume there&amp;rsquo;s much to gain when looking at these activities in their context, rather than separately.&lt;/p&gt;
&lt;p&gt;As a small side project, I could look into the best way of combining the different &lt;code&gt;.fit&lt;/code&gt;-files into one well-visualised multi-sport event. It would surprise me if no one else has done this before, but this idea gives me the best opportunity to dive into how these files are structured (&lt;em&gt;as I am totally unfamiliar with how they work&lt;/em&gt;) and how I could combine them in one multi-sport visualisation.&lt;/p&gt;
&lt;p&gt;I could use the data from different &lt;code&gt;.fit&lt;/code&gt;-files to display some maps of the course and compare the first and last running segments of a duathlon, for example. I could show a well-visualised race timeline with interesting annotations like weather conditions and elevation profiles, and the location of the highest achieved heart rate and power output. For friend groups participating in the same event, I could show different participants&amp;rsquo; data on the same visualisation, to easily let them compare their performance.&lt;/p&gt;</description></item><item><title>Target power to predicted race time</title><link>http://patrick.vanderspie.gl/notes/2024-08-15/</link><pubDate>Thu, 15 Aug 2024 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/notes/2024-08-15/</guid><description>&lt;p&gt;For both training and racing, I use a &lt;a href="https://www.stryd.com/eu/en"&gt;Stryd pod&lt;/a&gt;: a running power meter that allows me to base my running on my power output, instead of looking at my pace or heart rate (which are both influenced by elevation). The Stryd running pod calculates my &lt;a href="https://help.stryd.com/en/articles/6879345-critical-power-definition"&gt;Critical Power (CP)&lt;/a&gt;, which is similar to Functional Threshold Power (FTP). My CP is currently &lt;span class="tooltip"&gt;3.490 W/kg&lt;span class="tooltiptext"&gt;Data from intervals.icu&lt;/span&gt;&lt;/span&gt; (and was 3.75 W/kg at the time of writing) — something that I want to keep improving as I&amp;rsquo;m planning to run my second marathon mid-September.&lt;/p&gt;
&lt;h3 id="predicting-finish-time-with-stryd"&gt;Predicting finish time with Stryd&lt;/h3&gt;
&lt;p&gt;The Stryd app has two handy features: one predicts race calculations for a set of fixed distances (&lt;em&gt;1 mile, 5k, 10k, HM, and full marathon&lt;/em&gt;) and the other returns a target power + predicted race time based on CP for a given &lt;code&gt;GPX&lt;/code&gt;. I was wondering how they calculate these predicted race times, and stumbled upon &lt;a href="https://blog.stryd.com/2020/01/10/how-to-calculate-your-race-time-from-your-target-power/"&gt;a blog post&lt;/a&gt; by Stryd themselves.&lt;/p&gt;
&lt;p&gt;Their simplified formula — specifically meant for a flat course with no air resistance — is rather straightforward: $T = \frac{1.04 * d}{TP / m}$, where $T$ is the predicted race time in seconds, $TP$ is the target power for the race in watts, $m$ is the runner&amp;rsquo;s body weight in kilograms, and $d$ is the distance in meters:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;from&lt;/span&gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;datetime&lt;/span&gt; &lt;span style="font-weight:bold;text-decoration:underline"&gt;import&lt;/span&gt; timedelta
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;def&lt;/span&gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;predicted_time&lt;/span&gt;(d, TP, m):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	seconds = 1.04 * d / (TP / m)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="font-weight:bold;text-decoration:underline"&gt;return&lt;/span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;str&lt;/span&gt;(timedelta(seconds=seconds))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="in-flanders-fields-marathon-prediction"&gt;&amp;ldquo;In Flanders Fields&amp;rdquo; marathon prediction&lt;/h3&gt;
&lt;p&gt;For &lt;a href="https://marathons.be/over-iff/"&gt;my next marathon&lt;/a&gt;, I am trying to go for a time under 4 hours. As my target power is ~250 W, I would finish my next marathon in &lt;strong&gt;3 hours and 51 minutes&lt;/strong&gt;, in the &lt;span class="tooltip"&gt;best case scenario&lt;span class="tooltiptext"&gt;Flat course, but weather can have a big impact&lt;/span&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;d = 42195 &lt;span style="color:#888;font-style:italic"&gt;# marathon distance in m&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;TP = 250 &lt;span style="color:#888;font-style:italic"&gt;# target power in W&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;m = 79 &lt;span style="color:#888;font-style:italic"&gt;# weight in kg&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; predicted_time(d, TP, m)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt;&amp;#39;3:51:06.964800&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is pretty similar to the Stryd app&amp;rsquo;s estimated time based on the provided &lt;code&gt;GPX&lt;/code&gt; of the marathon course, which predicts I will run the marathon in around &lt;strong&gt;3 hours and 50 minutes&lt;/strong&gt; — if I can maintain an average power output of ~252 W. Using the simplified formula directly, however, gives me a bit more flexibility to see what my predicted time would be if I increase my target power or lose weight, but retain my CP:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;weight = &lt;span style="font-weight:bold;font-style:italic"&gt;range&lt;/span&gt;(80, 74, -1)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;time = [predicted_time(d, TP, w) &lt;span style="font-weight:bold;text-decoration:underline"&gt;for&lt;/span&gt; w &lt;span style="font-weight:bold"&gt;in&lt;/span&gt; weight]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span style="font-weight:bold;text-decoration:underline"&gt;for&lt;/span&gt; w, t &lt;span style="font-weight:bold"&gt;in&lt;/span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;zip&lt;/span&gt;(weight, time):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;... &lt;span style="font-weight:bold;font-style:italic"&gt;print&lt;/span&gt;(&lt;span style="color:#666;font-style:italic"&gt;f&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;{&lt;/span&gt;w&lt;span style="color:#666;font-style:italic"&gt;}&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt; kg — &lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;{&lt;/span&gt;t&lt;span style="color:#666;font-style:italic"&gt;}&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt;&amp;#39;80 kg — 3:54:02.496000&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt;&amp;#39;79 kg — 3:51:06.964800&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt;&amp;#39;78 kg — 3:48:11.433600&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt;&amp;#39;77 kg — 3:45:15.902400&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt;&amp;#39;76 kg — 3:42:20.371200&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt;&amp;#39;75 kg — 3:39:24.840000&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Stryd also just released &lt;a href="https://blog.stryd.com/2024/08/14/clayton-youngs-9th-place-finish-at-the-olympic-marathon/"&gt;a blog post&lt;/a&gt; about Clayton Young and his preparation for the Olympic Marathon in Paris, in which he finished 9th: Stryd predicted his finish time at 2:09:54, and he ultimately ran 2:08:44.&lt;/p&gt;</description></item><item><title>Pomodoro timer in a terminal</title><link>http://patrick.vanderspie.gl/notes/2024-08-14/</link><pubDate>Wed, 14 Aug 2024 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/notes/2024-08-14/</guid><description>&lt;hr&gt;
&lt;p&gt;I usually use the &lt;a href="https://en.wikipedia.org/wiki/Pomodoro_Technique"&gt;Pomodoro Technique&lt;/a&gt; to schedule my work: intervals of 25 minutes of work, followed by a 5 minute break. Traditionally, I used &lt;a href="https://pomofocus.io/"&gt;pomofocus.io&lt;/a&gt; as a timer in my browser that alerts me when an interval is over. As I often have a terminal emulator opened somewhere — and as I wanted to keep track of the number of finished &lt;em&gt;pomodori&lt;/em&gt; in Obsidian, it made more sense to create my own shell script that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Starts a 25 minute timer, alerting me when time runs out&lt;/li&gt;
&lt;li&gt;Gives me the option to take a break, starting a 5 minute timer&lt;/li&gt;
&lt;li&gt;Keeps alternating between work and break intervals until I stop working&lt;/li&gt;
&lt;li&gt;Keeps track of finished pomodori for the day in my Obsidian work vault&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="displaying-a-timer"&gt;Displaying a timer&lt;/h2&gt;
&lt;p&gt;Below, we define a function that takes a label (&lt;em&gt;e.g., working or taking a break&lt;/em&gt;) and the amount of seconds the countdown should take. We start by moving the text cursor to the upper left corner using &lt;code&gt;echo -ne '\033[2A'&lt;/code&gt;&lt;label for="sidenote-0" class="sidenote-number"&gt;&lt;/label&gt;&lt;input type="checkbox" id="sidenote-0" class="sidenote-toggle"&gt;&lt;span class="sidenote"&gt;&lt;a href="https://stackoverflow.com/a/72667369"&gt;StackOverflow&lt;/a&gt;&lt;/span&gt;, and then, as long as our variable &lt;code&gt;time_left&lt;/code&gt; is larger than -1:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Show the label in bold, using &lt;code&gt;\033[1m• $label\033[0m&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Format remaining time using &lt;code&gt;$(date -d@$time_left -u +%M:%S)&lt;/code&gt;, so that it shows as remaining time in minutes and seconds, instead of just seconds&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;\033[0K&lt;/code&gt; to delete text to the end of the line, and &lt;code&gt;\r&lt;/code&gt; to move to the beginning of the current line&lt;label for="sidenote-1" class="sidenote-number"&gt;&lt;/label&gt;&lt;input type="checkbox" id="sidenote-1" class="sidenote-toggle"&gt;&lt;span class="sidenote"&gt;&lt;a href="https://stackoverflow.com/a/5861713"&gt;StackOverflow&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Wait one second using &lt;code&gt;sleep&lt;/code&gt;, and substract 1 from the &lt;code&gt;time_left&lt;/code&gt; variable&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;display_timer() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;local&lt;/span&gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;label&lt;/span&gt;=&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;local&lt;/span&gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;time_left&lt;/span&gt;=&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;echo&lt;/span&gt; -ne &lt;span style="color:#666;font-style:italic"&gt;&amp;#39;\033[2A&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;text-decoration:underline"&gt;while&lt;/span&gt; [ &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$time_left&lt;/span&gt; -gt -1 ]; &lt;span style="font-weight:bold;text-decoration:underline"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;echo&lt;/span&gt; -ne &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;\033[1m• &lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$label&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;\033[0m — &lt;/span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;$(&lt;/span&gt;date -d@&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$time_left&lt;/span&gt; -u +%M:%S&lt;span style="font-weight:bold;text-decoration:underline"&gt;)&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;\033[0K\r&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sleep 1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ((time_left--))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;text-decoration:underline"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can start and display our work timer and break timer as shown below. We start a 25 minute timer (displayed as &lt;code&gt;• Work left — MM:SS&lt;/code&gt;), immediately followed by a 5 minute timer (displayed as &lt;code&gt;• Break left — MM:SS&lt;/code&gt;):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;WORK_TIME&lt;/span&gt;=&lt;span style="font-weight:bold;text-decoration:underline"&gt;$((&lt;/span&gt;60 * 25&lt;span style="font-weight:bold;text-decoration:underline"&gt;))&lt;/span&gt; &lt;span style="color:#888;font-style:italic"&gt;# Work time (25 minutes)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;BREAK_TIME&lt;/span&gt;=&lt;span style="font-weight:bold;text-decoration:underline"&gt;$((&lt;/span&gt;60 * 5&lt;span style="font-weight:bold;text-decoration:underline"&gt;))&lt;/span&gt; &lt;span style="color:#888;font-style:italic"&gt;# Break time (5 minutes)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;display_timer &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;Work left&amp;#34;&lt;/span&gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$WORK_TIME&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;display_timer &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;Break left&amp;#34;&lt;/span&gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$BREAK_TIME&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="keeping-track-of-s"&gt;Keeping track of 🍅&amp;rsquo;s&lt;/h2&gt;
&lt;p&gt;In my Obsidian journal, I have daily notes where I keep track of work done, to-dos, and ideas. I recently added a &lt;code&gt;pomodori&lt;/code&gt; field to the properties of my Markdown files, where I keep track of how many work intervals I have done that day:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-md" data-lang="md"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;date: 2024-08-14
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;type: research journal
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;pomodori: 🍅🍅🍅🍅
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I want this script to automatically add a new interval to this property, by first defining the path to today&amp;rsquo;s note and then appending a 🍅 to the end of the line of that property using &lt;code&gt;sed&lt;/code&gt;. As the property will always be on the fourth line of my notes, we can write:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;WORK_TIME&lt;/span&gt;=&lt;span style="font-weight:bold;text-decoration:underline"&gt;$((&lt;/span&gt;60 * 25&lt;span style="font-weight:bold;text-decoration:underline"&gt;))&lt;/span&gt; &lt;span style="color:#888;font-style:italic"&gt;# Work time (25 minutes)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;BREAK_TIME&lt;/span&gt;=&lt;span style="font-weight:bold;text-decoration:underline"&gt;$((&lt;/span&gt;60 * 5&lt;span style="font-weight:bold;text-decoration:underline"&gt;))&lt;/span&gt; &lt;span style="color:#888;font-style:italic"&gt;# Break time (5 minutes)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;JOURNAL&lt;/span&gt;=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;(⋯)/work/Research Journal&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;ENTRY&lt;/span&gt;=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$JOURNAL&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;/&lt;/span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;$(&lt;/span&gt;date +%Y-%m-%d&lt;span style="font-weight:bold;text-decoration:underline"&gt;)&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt; Research Journal.md&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;display_timer &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;Work left&amp;#34;&lt;/span&gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$WORK_TIME&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sed -i &lt;span style="color:#666;font-style:italic"&gt;&amp;#39;4s/$/🍅/&amp;#39;&lt;/span&gt; &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$ENTRY&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;display_timer &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;Break left&amp;#34;&lt;/span&gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$BREAK_TIME&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="user-input-to-keep-going"&gt;User input to keep going&lt;/h2&gt;
&lt;p&gt;Using &lt;code&gt;zenity&lt;/code&gt;, we can request user input to check if we want to switch from working to taking a break, and vice versa. We use &lt;code&gt;exec &amp;quot;$(readlink -f &amp;quot;$0&amp;quot;)&amp;quot;&lt;/code&gt;&lt;label for="sidenote-2" class="sidenote-number"&gt;&lt;/label&gt;&lt;input type="checkbox" id="sidenote-2" class="sidenote-toggle"&gt;&lt;span class="sidenote"&gt;&lt;a href="https://askubuntu.com/questions/356800"&gt;AskUbuntu&lt;/a&gt;&lt;/span&gt; to restart the script when switching from taking a break back to working:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;if&lt;/span&gt; zenity --question --title=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;Pomodoro&amp;#34;&lt;/span&gt; --text=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;Time for a break?&amp;#34;&lt;/span&gt;; &lt;span style="font-weight:bold;text-decoration:underline"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; display_timer &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;Break left&amp;#34;&lt;/span&gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$BREAK_TIME&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;text-decoration:underline"&gt;if&lt;/span&gt; zenity --question --title=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;Pomodoro&amp;#34;&lt;/span&gt; --text=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;Time to work?&amp;#34;&lt;/span&gt;; &lt;span style="font-weight:bold;text-decoration:underline"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;exec&lt;/span&gt; &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;$(&lt;/span&gt;readlink -f &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$0&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;)&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#888;font-style:italic"&gt;# Restart the script for another Pomodoro cycle&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;text-decoration:underline"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="putting-it-all-together"&gt;Putting it all together&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#888;font-weight:bold"&gt;#!/usr/bin/env bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;clear
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#888;font-style:italic"&gt;# Paths and file names&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;JOURNAL&lt;/span&gt;=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;(⋯)/work/Research Journal&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;ENTRY&lt;/span&gt;=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$JOURNAL&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;/&lt;/span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;$(&lt;/span&gt;date +%Y-%m-%d&lt;span style="font-weight:bold;text-decoration:underline"&gt;)&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt; Research Journal.md&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#888;font-style:italic"&gt;# Pomodoro timers (in seconds)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;WORK_TIME&lt;/span&gt;=&lt;span style="font-weight:bold;text-decoration:underline"&gt;$((&lt;/span&gt;60 * 25&lt;span style="font-weight:bold;text-decoration:underline"&gt;))&lt;/span&gt; &lt;span style="color:#888;font-style:italic"&gt;# Work time (25 minutes)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;BREAK_TIME&lt;/span&gt;=&lt;span style="font-weight:bold;text-decoration:underline"&gt;$((&lt;/span&gt;60 * 5&lt;span style="font-weight:bold;text-decoration:underline"&gt;))&lt;/span&gt; &lt;span style="color:#888;font-style:italic"&gt;# Break time (5 minutes)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#888;font-style:italic"&gt;# Function to display the timer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;display_timer() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;local&lt;/span&gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;label&lt;/span&gt;=&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;local&lt;/span&gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;time_left&lt;/span&gt;=&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;echo&lt;/span&gt; -ne &lt;span style="color:#666;font-style:italic"&gt;&amp;#39;\033[2A&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;text-decoration:underline"&gt;while&lt;/span&gt; [ &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$time_left&lt;/span&gt; -gt -1 ]; &lt;span style="font-weight:bold;text-decoration:underline"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;echo&lt;/span&gt; -ne &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;\033[1m• &lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$label&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;\033[0m — &lt;/span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;$(&lt;/span&gt;date -d@&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$time_left&lt;/span&gt; -u +%M:%S&lt;span style="font-weight:bold;text-decoration:underline"&gt;)&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;\033[0K\r&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sleep 1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ((time_left--))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;text-decoration:underline"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#888;font-style:italic"&gt;# Start the work session&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;display_timer &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;Work left&amp;#34;&lt;/span&gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$WORK_TIME&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#888;font-style:italic"&gt;# Add a 🍅 emoji to the fourth line of the journal entry&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sed -i &lt;span style="color:#666;font-style:italic"&gt;&amp;#39;4s/$/🍅/&amp;#39;&lt;/span&gt; &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$ENTRY&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#888;font-style:italic"&gt;# Prompt to take a break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;if&lt;/span&gt; zenity --question --title=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;Pomodoro&amp;#34;&lt;/span&gt; --text=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;Time for a break?&amp;#34;&lt;/span&gt;; &lt;span style="font-weight:bold;text-decoration:underline"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; display_timer &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;Break left&amp;#34;&lt;/span&gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$BREAK_TIME&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;text-decoration:underline"&gt;if&lt;/span&gt; zenity --question --title=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;Pomodoro&amp;#34;&lt;/span&gt; --text=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;Time to work?&amp;#34;&lt;/span&gt;; &lt;span style="font-weight:bold;text-decoration:underline"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;exec&lt;/span&gt; &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;$(&lt;/span&gt;readlink -f &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$0&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;)&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#888;font-style:italic"&gt;# Restart the script for another Pomodoro cycle&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;text-decoration:underline"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I have added &lt;code&gt;clear&lt;/code&gt; to the beginning of the script to clear the terminal screen before the script runs, just to ensure a clean display of the timer:&lt;/p&gt;
&lt;p&gt;










&lt;figure class=""&gt;

 &lt;div&gt;&lt;img loading="lazy" alt="Demonstration of Pomodoro timer" src=" /notes/20240814-pomodoro-demo.gif"&gt;&lt;/div&gt;

 
 
 &lt;div class="caption-container"&gt;
 &lt;figcaption&gt; Demonstration of Pomodoro timer &lt;/figcaption&gt;
 &lt;/div&gt;
 
 
&lt;/figure&gt;&lt;/p&gt;</description></item><item><title>Scraping TETR.IO Tetra League standings</title><link>http://patrick.vanderspie.gl/notes/2024-08-13/</link><pubDate>Tue, 13 Aug 2024 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/notes/2024-08-13/</guid><description>&lt;p&gt;Since 2022, I&amp;rsquo;ve regularly enjoyed playing a competitive Tetris variant named &lt;a href="https://tetr.io"&gt;TETR.IO&lt;/a&gt;. It&amp;rsquo;s been a while since I have played the game, but when visiting its website I read that the game just moved from it&amp;rsquo;s Alpha stage to Beta, and that the second season of TETR.IO&amp;rsquo;s &lt;code&gt;TETRA LEAGUE&lt;/code&gt; (the game&amp;rsquo;s competitive matchmaking mode) starts on the 16th of August.&lt;/p&gt;
&lt;p&gt;Something that I missed in the Alpha version of the game was the history of progression: I would have loved to see a plot that shows my rank and the game&amp;rsquo;s equivalent of my ELO score over time. With the second season of the game fast approaching, it is the perfect time to create a &lt;code&gt;cron&lt;/code&gt; job for a script that scrapes my &lt;a href="https://ch.tetr.io/u/geuze"&gt;TETR.IO profile&lt;/a&gt; and writes the current score to a file. The data itself could then be used to create my plot, and maybe showcase it on my website.&lt;/p&gt;
&lt;p&gt;Inspecting the &lt;code&gt;HTML&lt;/code&gt; of the TETR.IO profile pages, the score is normally displayed in the following &lt;code&gt;div&lt;/code&gt;. Because it is the off-season, however, there is no score to display:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;div class=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;card categorical&amp;#34;&lt;/span&gt; id=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;usercard_league&amp;#34;&lt;/span&gt; style=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;--color: #375433&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&amp;lt;h1&amp;gt;&amp;lt;img src=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;/res/league.svg&amp;#34;&lt;/span&gt;&amp;gt;TETRA LEAGUE&amp;lt;/h1&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&amp;lt;h6 id=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;user_league_np&amp;#34;&lt;/span&gt;&amp;gt;Off-season&amp;lt;/h6&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&amp;lt;div id=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;user_leagueset&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&amp;lt;div id=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;user_leaguestateset&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/div&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&amp;lt;div id=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;user_leaguestandingset&amp;#34;&lt;/span&gt; class=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;standingset&amp;#34;&lt;/span&gt;&amp;gt;abc&amp;lt;/div&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&amp;lt;/div&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	⋯
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/div&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Initially, I planned to simply scrape this using:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -s &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;https://ch.tetr.io/u/geuze&amp;#34;&lt;/span&gt; | grep -oP &lt;span style="color:#666;font-style:italic"&gt;&amp;#39;(?&amp;lt;=&amp;lt;h6 id=&amp;#34;user_league_np&amp;#34;&amp;gt;).*?(?=&amp;lt;/h6&amp;gt;)&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A simple &lt;code&gt;curl&lt;/code&gt; and &lt;code&gt;grep&lt;/code&gt; of the webpage won&amp;rsquo;t do, however, as the information seems to be loaded using Javascript. Before the beginning of this new season, I&amp;rsquo;ll look into scraping Javascript-rendered web pages using Python.&lt;/p&gt;</description></item><item><title>Partially ordered sets with cycles</title><link>http://patrick.vanderspie.gl/notes/2024-08-12/</link><pubDate>Mon, 12 Aug 2024 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/notes/2024-08-12/</guid><description>&lt;p&gt;A &lt;a href="https://mathworld.wolfram.com/PartiallyOrderedSet.html"&gt;partially ordered set&lt;/a&gt; — or &lt;em&gt;poset&lt;/em&gt; — $P = (A, \preceq)$ is a pair consisting of a set $A$ and a partial order $\preceq$ on $A$. This partial order is a binary relation on a set $A$ such that — for all $x, y, z \in A$ — it is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;reflexive ($x \preceq x$),&lt;/li&gt;
&lt;li&gt;antisymmetric ($x \preceq y$ and $y \preceq x$ imply $x = y$),&lt;/li&gt;
&lt;li&gt;and transitive ($x \preceq y$ and $y \preceq z$ imply $x \preceq z$).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For two elements $x, y \in P$, we say that $y$ &lt;a href="https://mathworld.wolfram.com/CoverRelation.html"&gt;covers&lt;/a&gt; $x$ if $x \prec y$ and there is no element $z \in P$ such that $x \prec z \prec y$. We write this as $x \lessdot y$.&lt;/p&gt;
&lt;p&gt;I assumed that every poset could be described as a &lt;a href="https://mathworld.wolfram.com/AcyclicDigraph.html"&gt;directed acylic graph&lt;/a&gt; through the cover relation between its elements. This intuitively makes sense to me, as cycles (e.g., $x \lessdot y$ and $y \lessdot x$) would be inconsistent with posets due to its antisymmetry, but $x \neq y$ given the definition of the cover relation. Thinking about cycles in orders reminded me of this great example on the link between directed acyclic graphs and genealogy, from the &lt;a href="https://books.google.be/books?id=mKkIGIea_BkC"&gt;&lt;em&gt;Handbook of Graph Theory&lt;/em&gt; by Jonathan L. Gross&lt;/a&gt;:&lt;/p&gt;
&lt;div class="quote-block"&gt;
 &lt;blockquote class="quote-content"&gt;A &amp;ldquo;family tree&amp;rdquo; is a digraph, where the orientation is traditionally given not by arrows but by the direction down for later generations. Despite the name, a family tree is usually not a tree, since people commonly marry distant cousins, knowingly or unknowingly. &lt;strong&gt;However, it is always a DAG, because if there were a cycle, everyone on it would be older than everyone else on the cycle.&lt;/strong&gt;&lt;/blockquote&gt;
&lt;/div&gt;&lt;div class="quote-source-link"&gt;
 &lt;a href="https://books.google.be/books?id=mKkIGIea_BkC" target="_blank" rel="noopener"&gt;Handbook of Graph Theory by Jonathan L. Gross&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;I did, however, stumble upon a paper titled &lt;a href="https://inria.hal.science/hal-01360144/document"&gt;&lt;em&gt;&amp;ldquo;Cyclic Ordering through Partial Orders&amp;rdquo;&lt;/em&gt; by Stefan Haar&lt;/a&gt;. Briefly scanning through the paper shows some interesting concepts, so I am certainly curious to learn more about this!&lt;/p&gt;</description></item><item><title>Describing activities with sparklines</title><link>http://patrick.vanderspie.gl/notes/2024-08-11/</link><pubDate>Sun, 11 Aug 2024 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/notes/2024-08-11/</guid><description>&lt;p&gt;Yesterday, I learned about &lt;a href="https://indieweb.org/sparkline"&gt;sparklines&lt;/a&gt; — &amp;ldquo;data-dense graphics with typographic resolution that is shown inline and in-context with relevant text.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;When thinking about how I could use sparklines in an original way within my personal website, I thought they would be interesting to convey properties of sports activities. One could add the elevation profile of a course &lt;span class="sparks bar-medium" style="color: darkgreen"&gt; 🏔️ {22,17,27,37,32,27,37,32,27,22,32,27,37,32,27,37,47,42,52,47} &lt;/span&gt;, or a heart rate curve &lt;span class="sparks dotline-medium" style="color: crimson"&gt; ❤ {22,17,27,37,32,27,37,32,27,22,32,27,37,32,27,37,47,42,52,47} &lt;/span&gt; and power output &lt;span class="sparks dotline-medium" style="color: purple"&gt; ⚡︎ {22,17,27,37,32,27,37,32,27,22,32,27,37,32,27,37,47,42,52,47} &lt;/span&gt; over time, as a sparkline within a blog post about a race.&lt;/p&gt;
&lt;p&gt;With the help of &lt;a href="https://github.com/aftertheflood/sparks/tree/master"&gt;Sparks&lt;/a&gt;, which is a typeface for creating sparklines in text, this was implemented quickly:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{{&amp;lt; sparkline class=&amp;#34;bar-medium&amp;#34; color=&amp;#34;darkgreen&amp;#34;&amp;gt;}} 🏔️ {22,17,27,37,32,27,37,32,27,22,32,27,37,32,27,37,47,42,52,47} {{&amp;lt;/ sparkline &amp;gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{{&amp;lt; sparkline class=&amp;#34;dotline-medium&amp;#34; color=&amp;#34;crimson&amp;#34;&amp;gt;}} ❤ {22,17,27,37,32,27,37,32,27,22,32,27,37,32,27,37,47,42,52,47} {{&amp;lt;/ sparkline &amp;gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{{&amp;lt; sparkline class=&amp;#34;dotline-medium&amp;#34; color=&amp;#34;purple&amp;#34; &amp;gt;}} ⚡︎ {22,17,27,37,32,27,37,32,27,22,32,27,37,32,27,37,47,42,52,47} {{&amp;lt;/ sparkline &amp;gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the future, I&amp;rsquo;d like to use actual data from &lt;a href="https://intervals.icu"&gt;intervals.icu&lt;/a&gt; for these sparklines.&lt;/p&gt;</description></item><item><title>Exploring breakfast spots with Overture Places</title><link>http://patrick.vanderspie.gl/notes/2024-08-10/</link><pubDate>Sat, 10 Aug 2024 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/notes/2024-08-10/</guid><description>&lt;p&gt;I recently learned about Overture places data through a blog post by &lt;a href="https://www.dbreunig.com/2024/07/31/towards-standardizing-place.html"&gt;Drew Breunig&lt;/a&gt;. This dataset &amp;ldquo;contains more than 53 million point representations of real-world entities: schools, businesses, (⋯), mountain peaks, and much more&amp;quot;&lt;label for="sidenote-0" class="sidenote-number"&gt;&lt;/label&gt;&lt;input type="checkbox" id="sidenote-0" class="sidenote-toggle"&gt;&lt;span class="sidenote"&gt;&lt;a href="https://docs.overturemaps.org/guides/places/"&gt;Places - Overture Maps Documentation&lt;/a&gt;&lt;/span&gt;. You can explore this data through the &lt;a href="https://explore.overturemaps.org"&gt;Overture Maps Explorer&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I regularly have breakfast with a friend, and we like exploring new breakfast places. The Overture dataset could provide us with new breakfast places in Brussels. For this, we need the &lt;a href="https://wiki.openstreetmap.org/wiki/Bounding_box"&gt;bounding box&lt;/a&gt; around the area of Brussels in which we&amp;rsquo;re interested in. We can find this using &lt;a href="http://bboxfinder.com/#50.832939,4.337368,50.858410,4.369812"&gt;bboxfinder.com&lt;/a&gt;. For this example, we take the bounding box around &lt;a href="https://en.wikipedia.org/wiki/Pentagon_(Brussels)"&gt;the Vijfhoek of Brussels&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;










&lt;figure class=""&gt;

 &lt;div&gt;&lt;img loading="lazy" alt="Screenshot of the bounding box around the Vijfhoek of Brussels" src=" /notes/20240810-bbox.png"&gt;&lt;/div&gt;

 
 
 &lt;div class="caption-container"&gt;
 &lt;figcaption&gt; Screenshot of the bounding box around the Vijfhoek of Brussels &lt;/figcaption&gt;
 &lt;/div&gt;
 
 
&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Checking out some of the regular places we visit through the Maps Explorer shows that they have the &lt;code&gt;&amp;quot;breakfast_and_brunch_restaurant&amp;quot;&lt;/code&gt; category in common. Using &lt;a href="https://duckdb.org/"&gt;&lt;code&gt;duckdb&lt;/code&gt;&lt;/a&gt;, we can download all places within our defined bounding box of &lt;code&gt;50.832939, 4.337368, 50.858410, 4.369812&lt;/code&gt;. The code below is based on an example from the &lt;a href="https://docs.overturemaps.org/guides/places/#data-usage-guidelines"&gt;Overture Maps website&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#888;font-style:italic"&gt;-- Load necessary modules
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;LOAD&lt;/span&gt; spatial;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;LOAD&lt;/span&gt; httpfs;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#888;font-style:italic"&gt;-- Set the AWS S3 region
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;SET&lt;/span&gt; s3_region = &lt;span style="color:#666;font-style:italic"&gt;&amp;#39;us-west-2&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#888;font-style:italic"&gt;-- Copy the filtered data from S3 to a local Parquet file
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;COPY&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;text-decoration:underline"&gt;SELECT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; id,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;text-decoration:underline"&gt;names&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; categories,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; websites,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; addresses,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ST_GeomFromWKB(geometry)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;text-decoration:underline"&gt;FROM&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; read_parquet(&lt;span style="color:#666;font-style:italic"&gt;&amp;#39;s3://overturemaps-us-west-2/release/2024-07-22.0/theme=places/*/*&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;text-decoration:underline"&gt;WHERE&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#888;font-style:italic"&gt;-- Filter by bounding box (xmin and ymin)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; bbox.xmin &lt;span style="font-weight:bold;text-decoration:underline"&gt;BETWEEN&lt;/span&gt; 4.337368 &lt;span style="font-weight:bold;text-decoration:underline"&gt;AND&lt;/span&gt; 4.369812 &lt;span style="font-weight:bold;text-decoration:underline"&gt;AND&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; bbox.ymin &lt;span style="font-weight:bold;text-decoration:underline"&gt;BETWEEN&lt;/span&gt; 50.832939 &lt;span style="font-weight:bold;text-decoration:underline"&gt;AND&lt;/span&gt; 50.858410
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;) &lt;span style="font-weight:bold;text-decoration:underline"&gt;TO&lt;/span&gt; &lt;span style="color:#666;font-style:italic"&gt;&amp;#39;vijfhoek.parquet&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next, we can query all the places where the primary category is &lt;code&gt;&amp;quot;breakfast_and_brunch_restaurant&amp;quot;&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;SELECT&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;text-decoration:underline"&gt;names&lt;/span&gt;.&lt;span style="font-weight:bold;text-decoration:underline"&gt;primary&lt;/span&gt; &lt;span style="font-weight:bold;text-decoration:underline"&gt;AS&lt;/span&gt; name, 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; addresses[1].freeform &lt;span style="font-weight:bold;text-decoration:underline"&gt;AS&lt;/span&gt; address, 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; websites[1] &lt;span style="font-weight:bold;text-decoration:underline"&gt;AS&lt;/span&gt; website
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;text-decoration:underline"&gt;FROM&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#666;font-style:italic"&gt;&amp;#39;vijfhoek.parquet&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;text-decoration:underline"&gt;WHERE&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; categories.&lt;span style="font-weight:bold;text-decoration:underline"&gt;primary&lt;/span&gt; = &lt;span style="color:#666;font-style:italic"&gt;&amp;#39;breakfast_and_brunch_restaurant&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;┌──────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ name │ address │ website │
│ varchar │ varchar │ varchar │
├──────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Flower food │ Rue Blaes 264 │ │
│ Le Père Tranquille │ Rue des Renards 4 │ │
│ Brussels Waffle Workshop │ Rue des Foulons 30 │ http://www.waffleworkshop.com │
│ Woodpecker 20 │ Rue Jourdan 20 │ │
│ EatClub Brussels │ Rue de Stassart 18 │ │
│ Café Boudin │ Rue Ravenstein 20 │ https://cafeboudin.be │
│ bloom_and_brunch_by_sabri │ Rue de la Paix 7 │ │
│ Lastra │ Rue du Conseil 24 │ │
│ Le Coin Des Saveurs │ Boulevard de l&amp;#39;Abattoir 19 │ │
│ Kandinsky │ Chaussée de Gand 37 │ https://kandinsky-family.be/ │
│ Restaurant Baurade │ Boulevard Anspach 153 │ │
│ Kafei Dansaert │ Rue Antoine Dansaert 57 │ https://kafei.be │
│ Le Odin Royal │ Oude Graanmarkt 2 │ │
│ Movenpick │ │ │
│ Woodpecker St. Cath. │ Quai au Bois à Brûler 27 │ │
│ Restaurant Al Andalus │ Rue de Ribaucourt 4 │ │
│ Gaufres and Waffles │ Chemin du Croquet 1 │ http://www.gaufresandwaffles.com │
│ Oats Day Long │ Europakruispunt 3 │ https://www.oatsdaylong.com │
│ Belrose cake │ Boulevard Émile Jacqmain 3 │ https://www.belrosecake.com/ │
│ Spread the moon │ Rue du Gentilhomme 13 │ https://www.instagram.com/spreadthemoon/ │
│ Longitude Nord-Sud │ Quai aux Pierres de Taille 14 │ http://longitude.blog4ever.com/ │
├──────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ 21 rows 3 columns │
└──────────────────────────────────────────────────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This is a good start, but lots of places we already visited are still missing from this list. We can query for all places where &lt;code&gt;'breakfast_and_brunch_restaurant'&lt;/code&gt; is listed under alternate categories using &lt;code&gt;OR 'breakfast_and_brunch_restaurant' = ANY (categories.alternate);&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m planning to pick this idea up later, and check if I can find a way to include more breakfast and brunch spots. In a next step, I could attempt to scrape the provided websites to check menus for our usual order.&lt;/p&gt;</description></item><item><title>intervals.icu, GitHub Actions, and Hugo shortcodes</title><link>http://patrick.vanderspie.gl/notes/2024-08-09/</link><pubDate>Fri, 09 Aug 2024 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/notes/2024-08-09/</guid><description>&lt;h2 id="intervalsicu-api"&gt;Intervals.icu API&lt;/h2&gt;
&lt;p&gt;I sync all my Strava activities to &lt;a href="https://intervals.icu"&gt;intervals.icu&lt;/a&gt;, which calculates my training load, fitness score, and my weekly ramp rate. To test out this platform&amp;rsquo;s &lt;code&gt;API&lt;/code&gt;, I wanted to calculate the distance that I ran or cycled given a custom date range, as this is something that I don&amp;rsquo;t immediately see inside intervals.icu itself. &lt;code&gt;GET /api/v1/athlete/{id}/activities&lt;/code&gt; returns a list of activities between the parameters &lt;code&gt;oldest&lt;/code&gt; and &lt;code&gt;newest&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;BASE_URL&lt;/span&gt;=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;https://intervals.icu/api/v1/athlete&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;OLDEST&lt;/span&gt;=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;2024-01-01&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;NEWEST&lt;/span&gt;=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;2024-12-31&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -s -u API_KEY:&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$API_KEY&lt;/span&gt; &lt;span style="color:#666;font-style:italic"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$BASE_URL&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;/&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$INTERVALS_UID&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;/activities?oldest=&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$OLDEST&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;&amp;amp;newest=&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$NEWEST&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As we can&amp;rsquo;t select specific activity types through the &lt;code&gt;API&lt;/code&gt; (we&amp;rsquo;re only interested in runs for this example, but this list contains all types of activities), I made use of &lt;a href="https://jqlang.github.io/jq/"&gt;&lt;code&gt;jq&lt;/code&gt; — &amp;ldquo;a lightweight and flexible command-line &lt;code&gt;JSON&lt;/code&gt; processor&amp;rdquo;&lt;/a&gt; — to select the name, start time, and distance of running activities only:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;BASE_URL&lt;/span&gt;=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;https://intervals.icu/api/v1/athlete&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;OLDEST&lt;/span&gt;=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;2024-01-01&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;NEWEST&lt;/span&gt;=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;2024-12-31&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -s -u API_KEY:&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$API_KEY&lt;/span&gt; &lt;span style="color:#666;font-style:italic"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$BASE_URL&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;/&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$INTERVALS_UID&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;/activities?oldest=&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$OLDEST&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;&amp;amp;newest=&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$NEWEST&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt; | &lt;span style="color:#666;font-style:italic"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;jq &lt;span style="color:#666;font-style:italic"&gt;&amp;#39;[.[] | select(.type == &amp;#34;Run&amp;#34;) | {name, start_date_local, distance}]&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style=""&gt;⋯&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;name&amp;#34;: &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;Night Run&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;start_date_local&amp;#34;: &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;2024-08-06T21:44:54&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;distance&amp;#34;: 6699
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;name&amp;#34;: &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;Afternoon Run&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;start_date_local&amp;#34;: &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;2024-08-06T16:06:24&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;distance&amp;#34;: 3400.5
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;name&amp;#34;: &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;Evening Run&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;start_date_local&amp;#34;: &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;2024-08-04T20:58:21&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;distance&amp;#34;: 4928
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style=""&gt;⋯&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This shows that our filter for running activities works. To now sum the distance of all our activities, we just need to select the distance of every activity and map &lt;code&gt;add&lt;/code&gt; over it. This returns the total distance in meters.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;BASE_URL&lt;/span&gt;=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;https://intervals.icu/api/v1/athlete&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;OLDEST&lt;/span&gt;=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;2024-01-01&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;NEWEST&lt;/span&gt;=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;2024-12-31&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -s -u API_KEY:&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$API_KEY&lt;/span&gt; &lt;span style="color:#666;font-style:italic"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$BASE_URL&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;/&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$INTERVALS_UID&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;/activities?oldest=&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$OLDEST&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;&amp;amp;newest=&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$NEWEST&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt; | &lt;span style="color:#666;font-style:italic"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;jq &lt;span style="color:#666;font-style:italic"&gt;&amp;#39;map(select(.type == &amp;#34;Run&amp;#34;) | .distance) | add&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;701168.5
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="github-actions-for-hugo-shortcode"&gt;GitHub Actions for Hugo shortcode&lt;/h2&gt;
&lt;p&gt;As I wanted to do something with this distance, I made a GitHub Actions workflow that calculates the distance every day at midnight and uses &lt;code&gt;sed&lt;/code&gt; to replace the Hugo variable &lt;code&gt;.Site.Params.distanceRun&lt;/code&gt;. Using this variable, I created a Hugo shortcode &lt;code&gt;{{&amp;lt; distance_run &amp;gt;}}&lt;/code&gt; that returns the distance run in kilometers:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{{- $distanceMeters := .Site.Params.distanceRun -}}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{{- $distanceKilometers := div $distanceMeters 1000 -}}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{{ printf &amp;#34;%.1f&amp;#34; $distanceKilometers }} km
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Using &lt;code&gt;{{&amp;lt; distance_run &amp;gt;}}&lt;/code&gt; in a Hugo content file returns: 470.5 km.
I can put this value in a &lt;a href="http://patrick.vanderspie.gl/notes/2024-08-08/"&gt;tooltip&lt;/a&gt; with an explanation of the value, which is displayed as &lt;span class="tooltip"&gt;470.5 km&lt;span class="tooltiptext"&gt;Total distance since 1st of Jan.&lt;/span&gt;&lt;/span&gt;:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;{{&amp;lt; tooltip &amp;gt;}}{{&amp;lt; distance_run &amp;gt;}} | Total distance since 1st of Jan.{{&amp;lt;/ tooltip &amp;gt;}}
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>Tooltip on mouse hover with Hugo</title><link>http://patrick.vanderspie.gl/notes/2024-08-08/</link><pubDate>Thu, 08 Aug 2024 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/notes/2024-08-08/</guid><description>&lt;p&gt;I added custom &lt;span class="tooltip"&gt;tooltips&lt;span class="tooltiptext"&gt;Just like this one!&lt;/span&gt;&lt;/span&gt; to this website, as I want to provide extra information to specific text in my posts and notes. This can be done using regular &lt;a href="https://gohugo.io/content-management/shortcodes/"&gt;shortcodes&lt;/a&gt;, which are simple snippets inside a content file that Hugo will render using a &lt;code&gt;HTML&lt;/code&gt; template:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{{&amp;lt; tooltip outer_text=&amp;#34;tooltips&amp;#34; tooltip_text=&amp;#34;Just like this one!&amp;#34; &amp;gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This works fine if we just provide simple, static text. One of the criteria for my tooltip shortcode, however, is that I should be able to put other shortcodes inside them, as I have a couple of shortcodes that make use of variables that are updated automatically using GitHub Actions. One example of this is the number of kilometers I ran this year &lt;em&gt;&lt;span class="tooltip"&gt;(470.5 km, currently)&lt;span class="tooltiptext"&gt;Updated using GitHub actions + intervals.icu &lt;/span&gt;&lt;/span&gt;&lt;/em&gt;, which I calculate using the &lt;a href="https://intervals.icu/"&gt;intervals.icu&lt;/a&gt; &lt;code&gt;API&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;As far as I know, there is no standard way of adding these tooltips in Hugo. I created them myself by using paired shortcodes and using &lt;code&gt;.Inner&lt;/code&gt; to return the content between the opening and closing shortcode tags, which allows us to do the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{{&amp;lt; tooltip &amp;gt;}} {{&amp;lt; inner_shortcode &amp;gt;}} {{&amp;lt;/ tooltip &amp;gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, we can get the contents of the inner shortcode through &lt;code&gt;.Inner&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;span class=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;tooltip&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {{- .Inner | safeHTML -}}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;span class=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;tooltiptext&amp;#34;&lt;/span&gt;&amp;gt;{{- .Inner | safeHTML -}}&amp;lt;/span&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/span&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We want to put some text as the outer text of the tooltip, and other text in the tooltip box itself, however. Through a hack provided by someone on the &lt;a href="https://discourse.gohugo.io/t/shortcode-nested-shortcode-multiple-inner/27441/9"&gt;Hugo forum&lt;/a&gt;, we can split up &lt;code&gt;.Inner&lt;/code&gt; by providing a custom delimiter. For my tooltips, I divide the contents of the paired shortcodes in the outer text and the tooltip text using &lt;code&gt;|&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{{- $children := split .Inner &amp;#34; | &amp;#34; -}}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;span class=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;tooltip&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {{- index $children 0 | safeHTML -}}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;span class=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;tooltiptext&amp;#34;&lt;/span&gt;&amp;gt;{{- index $children 1 | safeHTML -}}&amp;lt;/span&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/span&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This way, I can define tooltips like this, for example: &lt;span class="tooltip"&gt; 470.5 km&lt;span class="tooltiptext"&gt;Updated using GitHub actions + intervals.icu &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{{&amp;lt; tooltip &amp;gt;}} {{&amp;lt; distance_run &amp;gt;}} km | See intervals.icu {{&amp;lt;/ tooltip &amp;gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Daily notes with GitHub Actions</title><link>http://patrick.vanderspie.gl/notes/2024-08-07/</link><pubDate>Wed, 07 Aug 2024 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/notes/2024-08-07/</guid><description>&lt;p&gt;I am using &lt;a href="https://github.com/features/actions"&gt;GitHub Actions&lt;/a&gt; to automatically create new daily notes on this website. Every day at midnight, a GitHub Action checks the &lt;code&gt;content/notes&lt;/code&gt; folder for a file titled &lt;code&gt;%Y-%m-%d.md&lt;/code&gt; (matching the current date). If this file does not yet exist, a new &lt;code&gt;%Y-%m-%d.md&lt;/code&gt; file with a standard &lt;a href="https://gohugo.io/content-management/front-matter/"&gt;Hugo front matter&lt;/a&gt; — filled in with the current date and a placeholder title — is created.&lt;/p&gt;
&lt;p&gt;To keep track of my daily writing streak, I also need to check if the previous day&amp;rsquo;s note was modified, and update my streak accordingly. I do this using a combination of &lt;code&gt;git&lt;/code&gt;, &lt;code&gt;grep&lt;/code&gt;, and &lt;code&gt;sed&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="git-log"&gt;&lt;code&gt;git log&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;a href="https://git-scm.com/docs/git-log"&gt;&lt;code&gt;git log&lt;/code&gt;&lt;/a&gt; command shows the commit log, which is used to check if there have been any other commits involving the previous day&amp;rsquo;s note, outside of its creation by GitHub Actions. If this is the case, there should be more than one commit involving this file, and I can thus assume that I have written something. Based on this output, the existing streak — which is stored in the &lt;a href="https://gohugo.io/getting-started/configuration/#configuration-file"&gt;&lt;code&gt;hugo.toml&lt;/code&gt;&lt;/a&gt; configuration file — is updated.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;PREV_DATE&lt;/span&gt;=&lt;span style="font-weight:bold;text-decoration:underline"&gt;$(&lt;/span&gt;date -d &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;${&lt;/span&gt;{ env.DATE &lt;span style="color:#666;font-style:italic"&gt;}&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;} -1 day&amp;#34;&lt;/span&gt; +&lt;span style="color:#666;font-style:italic"&gt;&amp;#39;%Y-%m-%d&amp;#39;&lt;/span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;if&lt;/span&gt; [[ &lt;span style="font-weight:bold;text-decoration:underline"&gt;$(&lt;/span&gt;git log --name-only --since=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;24 hours ago&amp;#34;&lt;/span&gt; &lt;span style="color:#666;font-style:italic"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	 --pretty=format: -- &lt;span style="color:#666;font-style:italic"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	 content/notes/&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$PREV_DATE&lt;/span&gt;.md | &lt;span style="color:#666;font-style:italic"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	 grep -c content/notes/&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$PREV_DATE&lt;/span&gt;.md&lt;span style="font-weight:bold;text-decoration:underline"&gt;)&lt;/span&gt; -gt 1 ]]; &lt;span style="font-weight:bold;text-decoration:underline"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;echo&lt;/span&gt; &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;MODIFIED=true&amp;#34;&lt;/span&gt; &amp;gt;&amp;gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$GITHUB_ENV&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;else&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;font-style:italic"&gt;echo&lt;/span&gt; &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;MODIFIED=false&amp;#34;&lt;/span&gt; &amp;gt;&amp;gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$GITHUB_ENV&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For this to work, however, we need to &lt;a href="https://stackoverflow.com/a/62335935"&gt;pass the &lt;code&gt;HEAD&lt;/code&gt;&amp;rsquo;s &lt;code&gt;SHA&lt;/code&gt; as a &lt;code&gt;ref&lt;/code&gt; to the checkout&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- name: Checkout repository
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; uses: actions/checkout@v3
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; with:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ref: ${{ github.event.pull_request.head.sha }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; fetch-depth: 0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="grep"&gt;&lt;code&gt;grep&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;To find the current value of the writing streak in the configuration file — and the corresponding date that matches this streak — I use &lt;code&gt;grep&lt;/code&gt;. These outputs are stored in environment variables.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;CURRENT_STREAK&lt;/span&gt;=&lt;span style="font-weight:bold;text-decoration:underline"&gt;$(&lt;/span&gt;grep -Po &lt;span style="color:#666;font-style:italic"&gt;&amp;#39;(?&amp;lt;=CURRENT_WRITING_STREAK = )\d+&amp;#39;&lt;/span&gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$TOML_FILE&lt;/span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;CURRENT_STREAK_DATE&lt;/span&gt;=&lt;span style="font-weight:bold;text-decoration:underline"&gt;$(&lt;/span&gt;grep -Po &lt;span style="color:#666;font-style:italic"&gt;&amp;#39;(?&amp;lt;=CURRENT_WRITING_STREAK_DATE = )\d{4}-\d{2}-\d{2}&amp;#39;&lt;/span&gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$TOML_FILE&lt;/span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="sed"&gt;&lt;code&gt;sed&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;The streak value in the configuration file is updated using &lt;code&gt;sed&lt;/code&gt;, based on our earlier result from the &lt;code&gt;git log&lt;/code&gt; command. We replace the current streak value with &lt;code&gt;$((CURRENT_STREAK + 1))&lt;/code&gt; if there is more than one commit involving the previous day&amp;rsquo;s note, or replace the streak with &lt;code&gt;0&lt;/code&gt; otherwise. This new streak is stored in the &lt;code&gt;$NEW_STREAK&lt;/code&gt; environment variable. We also do the same to keep track of the best writing streak to date.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sed -i &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;s/CURRENT_WRITING_STREAK = &lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$CURRENT_STREAK&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;/CURRENT_WRITING_STREAK = &lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$NEW_STREAK&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;/&amp;#34;&lt;/span&gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$TOML_FILE&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sed -i &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;s/CURRENT_WRITING_STREAK_DATE = &lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$CURRENT_STREAK_DATE&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;/CURRENT_WRITING_STREAK_DATE = &lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;${&lt;/span&gt;{ env.DATE &lt;span style="color:#666;font-style:italic"&gt;}&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;}/&amp;#34;&lt;/span&gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$TOML_FILE&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The above &lt;code&gt;sed&lt;/code&gt; command kept throwing an error, however: &lt;code&gt;sed: -e (...) unterminated 's' command&lt;/code&gt;. I tried everything from attempting to escape underscores, to adding &lt;code&gt;--&lt;/code&gt; to &lt;code&gt;sed&lt;/code&gt; (as maybe the hyphens in the dates could be confused with a &lt;code&gt;sed&lt;/code&gt; option that made something break), as I first thought that these characters were possibly causing these issues.&lt;/p&gt;
&lt;p&gt;In the end, I realised that the issue was caused due to &lt;code&gt;grep&lt;/code&gt; matching multiple lines in the &lt;code&gt;hugo.toml&lt;/code&gt; — which also included newlines and spaces. I did not realise that newlines would be included in the environment variables, but making sure the regex match was only limited to the &lt;code&gt;CURRENT_WRITING_STREAK&lt;/code&gt; variable in the configuration file and trimming any newlines, resolved the issue:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;CURRENT_STREAK&lt;/span&gt;=&lt;span style="font-weight:bold;text-decoration:underline"&gt;$(&lt;/span&gt;&lt;span style="font-weight:bold;font-style:italic"&gt;echo&lt;/span&gt; &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$CURRENT_STREAK&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt; | tr -d &lt;span style="color:#666;font-style:italic"&gt;&amp;#39;\n&amp;#39;&lt;/span&gt; | tr -d &lt;span style="color:#666;font-style:italic"&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;CURRENT_STREAK_DATE&lt;/span&gt;=&lt;span style="font-weight:bold;text-decoration:underline"&gt;$(&lt;/span&gt;&lt;span style="font-weight:bold;font-style:italic"&gt;echo&lt;/span&gt; &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;$CURRENT_STREAK_DATE&lt;/span&gt;&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&lt;/span&gt; | tr -d &lt;span style="color:#666;font-style:italic"&gt;&amp;#39;\n&amp;#39;&lt;/span&gt; | tr -d &lt;span style="color:#666;font-style:italic"&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;By double-checking the used regex and removing unwanted characters, the &lt;code&gt;sed&lt;/code&gt; command could successfully update the values in the &lt;code&gt;hugo.toml&lt;/code&gt; file without errors:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Writing streak of
&lt;span class="tooltip"&gt;
	
	
	
	
	0 days&lt;span class="tooltiptext"&gt;Updated on 12 Aug 2026
&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Best writing streak to date is
&lt;span class="tooltip"&gt;
	
	
	
	
	
	20 days&lt;span class="tooltiptext"&gt;Achieved on 27 Aug 2024
&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Sharing daily notes</title><link>http://patrick.vanderspie.gl/posts/daily-notes/</link><pubDate>Wed, 07 Aug 2024 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/posts/daily-notes/</guid><description>&lt;p&gt;For my work, I picked up the habit of transferring my daily notes and insights from my physical notebooks to an &lt;a href="https://obsidian.md/"&gt;Obsidian&lt;/a&gt; vault. Thanks to using Obsidian and &lt;code&gt;git&lt;/code&gt;, I have a locally-stored, version-controlled, and easily searchable overview of my work that I can reference when preparing reports and presentations.&lt;/p&gt;
&lt;p&gt;Equivalently, I miss a digital space where I can transfer personal insights, store interesting links and quotes, and write down notes unrelated to my work. Topics of these notes could include everything from programming, research, and literature, to physical exercise and ceramics.&lt;/p&gt;
&lt;h3 id="why-make-these-notes-public"&gt;Why make these notes public?&lt;/h3&gt;
&lt;p&gt;I could start a new Obsidian vault for these notes, but I think they should be someplace public as I want to &lt;a href="https://notes.andymatuschak.org/Work_with_the_garage_door_up"&gt;“work with my garage door up.”&lt;/a&gt; I also want to keep up a daily writing streak: if I would just create another private Obsidian vault, it&amp;rsquo;ll be too easy to convince myself to skip writing to do other things instead. Public challenges like &lt;a href="https://100daystooffload.com/"&gt;&lt;code&gt;#100DaysToOffload&lt;/code&gt;&lt;/a&gt; seem appealing to participate in, as well.&lt;/p&gt;
&lt;h3 id="why-share-these-on-a-personal-website"&gt;Why share these on a personal website?&lt;/h3&gt;
&lt;p&gt;We can write whatever we want on personal websites, without being vulnerable to tech companies and their social media algorithms + keeping ownership of content. I am currently hosting this website through &lt;a href="https://pages.github.com/"&gt;GitHub Pages&lt;/a&gt;, but I can pack up my content and move it elsewhere whenever I want. Read more about this in this &lt;a href="https://matthiasott.com/articles/into-the-personal-website-verse"&gt;great article by Matthias Ott&lt;/a&gt;:&lt;/p&gt;
&lt;div class="quote-block"&gt;
 &lt;blockquote class="quote-content"&gt;If you decide to publish your work on a platform like Medium, you&amp;rsquo;re giving away control over it. What if Medium suddenly decided to extend the already existing paywall to all articles? There&amp;rsquo;s not much you could do about it. Simply because you don&amp;rsquo;t own your content anymore.&lt;/blockquote&gt;
&lt;/div&gt;&lt;div class="quote-source-link"&gt;
 &lt;a href="https://matthiasott.com/articles/into-the-personal-website-verse" target="_blank" rel="noopener"&gt;Matthias Ott&lt;/a&gt;
&lt;/div&gt;
&lt;div class="quote-block"&gt;
 &lt;blockquote class="quote-content"&gt;But maybe the most compelling reason why a personal website (⋯) is incredibly valuable is this: community. Since the days of &amp;ldquo;guest books&amp;rdquo;, personal websites have been a place to receive feedback and discuss ideas and concepts with others. (⋯) Now imagine, for a moment, an environment where a decentralized fabric of connected personal sites allows everyone to publish their own content but also enables each individual to engage in an open discussion – answering, challenging, and acknowledging the ideas of others through this universe of personal sites.&lt;/blockquote&gt;
&lt;/div&gt;&lt;div class="quote-source-link"&gt;
 &lt;a href="https://matthiasott.com/articles/into-the-personal-website-verse" target="_blank" rel="noopener"&gt;Matthias Ott&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;To allow for this engagement, I&amp;rsquo;m planning to add &lt;a href="https://indieweb.org/Webmention"&gt;Webmentions&lt;/a&gt; to this website soon.&lt;/p&gt;
&lt;h3 id="why-share-unpolished-work"&gt;Why share unpolished work?&lt;/h3&gt;
&lt;p&gt;By trying to write and publish a quick note every day, I&amp;rsquo;ll hopefully improving my writing. Not all of these notes will be polished, which is why I plan to keep them separate from &lt;a href="http://patrick.vanderspie.gl/posts"&gt;my regular posts&lt;/a&gt;. It is okay to create unpolished things — a quote from &lt;a href="https://robinrendle.com/notes/the-story-is-a-codebase/"&gt;Robin Rendle&lt;/a&gt;:&lt;/p&gt;
&lt;div class="quote-block"&gt;
 &lt;blockquote class="quote-content"&gt;I feel like I&amp;rsquo;m free now to write absolute junk. And this is vital for any creative thing! You have to feel like your mistakes won&amp;rsquo;t be judged, that there&amp;rsquo;s no one watching you write shameful, embarrassing things. Because if you have all that pressure of trying to write the next great American novel then I reckon you&amp;rsquo;re destined to fail.&lt;/blockquote&gt;
&lt;/div&gt;&lt;div class="quote-source-link"&gt;
 &lt;a href="https://robinrendle.com/notes/the-story-is-a-codebase/" target="_blank" rel="noopener"&gt;Robin Rendle&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Hopefully, these notes give me inspiration to write some longer posts, where I can combine ideas and flesh out concepts of multiple related notes.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="writing-streak"&gt;Writing streak&lt;/h3&gt;
&lt;p&gt;I currently have a writing streak of &lt;span class="tooltip"&gt;



0 days&lt;span class="tooltiptext"&gt;Updated on 12 Aug 2026&lt;/span&gt;&lt;/span&gt;, and my largest streak to date is &lt;span class="tooltip"&gt;




20 days&lt;span class="tooltiptext"&gt;Achieved on 27 Aug 2024&lt;/span&gt;&lt;/span&gt;. You can find these daily notes &lt;a href="http://patrick.vanderspie.gl/notes"&gt;here&lt;/a&gt;. To find the note for a corresponding date, go to &lt;code&gt;/notes/YYYY-MM-DD&lt;/code&gt;. Each date since &lt;code&gt;2024-08-07&lt;/code&gt; should have an existing entry, even if I did not write anything that day.&lt;/p&gt;</description></item><item><title>Obsidian.md, Espanso, and llm</title><link>http://patrick.vanderspie.gl/posts/obsidian-espanso-llm/</link><pubDate>Tue, 23 Jul 2024 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/posts/obsidian-espanso-llm/</guid><description>&lt;p&gt;I switched from Notion to &lt;a href="https://obsidian.md/"&gt;Obsidian.md&lt;/a&gt; to keep track of meeting notes, to store highlights from scientific papers (using a &lt;a href="https://github.com/mgmeyers/obsidian-zotero-integration"&gt;Zotero plugin&lt;/a&gt;), and to maintain a knowledge base for my PhD research.&lt;/p&gt;
&lt;h2 id="obsidian-and-llm"&gt;Obsidian and &lt;code&gt;llm&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;To summarise or rephrase parts of notes and paper highlights, I often use OpenAI models through &lt;a href="https://github.com/simonw/llm"&gt;&lt;code&gt;llm&lt;/code&gt;&lt;/a&gt;, a CLI utility that provides an easy way to interact with the OpenAI API. Traditionally, my workflow consisted of piping Markdown files from my Obsidian vault to &lt;code&gt;llm&lt;/code&gt;, combining them with a system prompt that described the requested task.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cat papers/paper.md | llm -m &lt;span style="color:#666;font-style:italic"&gt;&amp;#39;gpt-4o&amp;#39;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-s &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;Summarise the methodology described in the provided paper notes&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I then copied the model output from the terminal and pasted it in a custom callout that I specifically defined for LLM-generated content (as to keep it separate from my own writing), giving me a first rough draft that I can edit later.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;callout&lt;/span&gt;[data-callout=&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;llm&amp;#34;&lt;/span&gt;] {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;--callout-color&lt;/span&gt;: 0, 100, 100;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;--callout-icon&lt;/span&gt;: bot;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A main disadvantage, however, is that I kept switching between Obsidian and the terminal to copy and paste model output. Another disadvantage was that I had no control over which lines from the relevant file to send to OpenAI when piping the full contents of a file to &lt;code&gt;llm&lt;/code&gt;&lt;label for="sidenote-0" class="sidenote-number"&gt;&lt;/label&gt;&lt;input type="checkbox" id="sidenote-0" class="sidenote-toggle"&gt;&lt;span class="sidenote"&gt;I am sure that there are plenty of ways to &lt;code&gt;cat&lt;/code&gt; specific lines only given a file, but I assume for this you need to provide specific line numbers, making the process a bit more complex.&lt;/span&gt;.&lt;/p&gt;
&lt;h2 id="obsidian-and-espanso"&gt;Obsidian and Espanso&lt;/h2&gt;
&lt;p&gt;Outside of tagging LLM output, I also use &lt;a href="https://help.obsidian.md/Editing+and+formatting/Callouts#Customize+callouts"&gt;custom Obsidian callouts&lt;/a&gt; to highlight definitions, examples, and quotes from papers and textbooks. For this, I started using &lt;a href="https://espanso.org/"&gt;Espanso&lt;/a&gt; — a text expander that automatically replaces specific keywords with predefined text. This helps me avoid repeatedly typing callout boilerplate:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- trigger: &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;:def&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; replace: &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&amp;gt; [!Definition] ⋯\n&amp;gt; ⋯&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- trigger: &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;:ex&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; replace: &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&amp;gt; [!Example]- ⋯ \n&amp;gt; ⋯&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Every time I type &lt;code&gt;:def&lt;/code&gt; — inside or outside of Obsidian — it replaces this keyword with the boilerplate that is needed to define a &lt;code&gt;Definition&lt;/code&gt; callout in Obsidian. Other custom triggers include arrows (←, →), dots (⋯, ⋮), and dashes (—) that I use in notes, and abbreviations for commonly used words (all preceded by the &lt;code&gt;:&lt;/code&gt; character, which I have reserved for Espanso keywords only).&lt;/p&gt;
&lt;h3 id="regex-triggers-arguments-and-shell-commands"&gt;Regex Triggers, Arguments, and Shell Commands&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://espanso.org/docs/matches/regex-triggers/"&gt;Regex triggers&lt;/a&gt; are an advanced alternative to regular triggers in Espanso. Instead of the static triggers shown above, these dynamic triggers provide flexibility through regex syntax and the use of named groups to pass arguments to expansions. The following two examples are taken from the Espanso documentation:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - regex: &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;:greet\\((?P&amp;lt;person&amp;gt;.*)\\)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; replace: &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;Hi {{person}}!&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can also execute scripts and shell commands through Espanso:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - regex: &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;=sum\\((?P&amp;lt;num1&amp;gt;.*?),(?P&amp;lt;num2&amp;gt;.*?)\\)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; replace: &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;{{result}}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; vars:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - name: result
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; type: shell
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; params:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cmd: &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;expr $ESPANSO_NUM1 + $ESPANSO_NUM2&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="expanding-llm-output"&gt;Expanding LLM Output&lt;/h2&gt;
&lt;p&gt;My initial goal was to create a new trigger — &lt;code&gt;:llm(⋯)&lt;/code&gt; — that allows for the following workflow: copy the text that we want the LLM to work with to the system&amp;rsquo;s clipboard (so that we don&amp;rsquo;t have to pipe a full file), type the trigger with the system prompt in the parenthesis, and expand this trigger to the custom LLM callout in Obsidian (with the system prompt as title, and the output of the LLM as the body of the callout). The trigger &lt;code&gt;:llm(&amp;quot;Summarise the provided text.&amp;quot;)&lt;/code&gt; would expand to:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; [!llm]- &amp;#34;Summarise the provided text.&amp;#34; 💬
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;⋯ (→ Summary of text currently in clipboard)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="limitation-of-regex-triggers"&gt;Limitation of Regex Triggers&lt;/h3&gt;
&lt;p&gt;Regex triggers have a limitation where the maximum length of a regex match, including captured named groups, are restricted to 30 characters&lt;label for="sidenote-1" class="sidenote-number"&gt;&lt;/label&gt;&lt;input type="checkbox" id="sidenote-1" class="sidenote-toggle"&gt;&lt;span class="sidenote"&gt;&lt;a href="https://espanso.org/docs/matches/regex-triggers/#limitations"&gt;Regex triggers - Espanso Documentation&lt;/a&gt;&lt;/span&gt;. This constraint is intended to enhance performance, but makes it harder to write an expressive system prompt.&lt;/p&gt;
&lt;p&gt;To circumvent this issue, we can use an LLM to first write us a full-sized prompt based on one or two provided keywords (as to keep our trigger under 30 characters) that we can then feed to our main LLM.&lt;/p&gt;
&lt;p&gt;We could do this in one call — asking to expand the prompt and then use this prompt to perform the task at hand — but this would make it harder to extract the expanded prompt for the title for our custom callout. Another approach would be to provide the callout boilerplate to &lt;code&gt;llm&lt;/code&gt;, asking it to return the filled-in callout; but as API calls are cheap, we&amp;rsquo;ll go with the most straightforward approach:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- regex: &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;:llm\\((?P&amp;lt;userprompt&amp;gt;.*?)\\)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; replace: &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&amp;gt; [!llm]- \&amp;#34;{{prompt}}\&amp;#34; 💬\n⋯\n\n&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; vars:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - name: prompt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; type: shell
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; params:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cmd: &amp;#34;echo $ESPANSO_USERPROMPT | llm -s
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; \ &amp;#39;Expand provided keywords to a short but effective, 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; \ imperative one-sentence prompt in UK English.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; \ The final output when using this prompt should be 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; \ short and to the point.&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For now, if we type &lt;code&gt;:llm(explain to 5yo)&lt;/code&gt;, we get the following in return:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt; [!llm]- &amp;#34;Explain the provided text in simple words 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;that a 5-year-old can easily understand.&amp;#34; 💬
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;⋯
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="passing-full-sized-prompt"&gt;Passing Full-Sized Prompt&lt;/h3&gt;
&lt;p&gt;Now that we can circumvent our character limit and have access to our full-sized prompt, we just have to provide it to another call of &lt;code&gt;llm&lt;/code&gt;. We can access the full-sized prompt by using the variable name in all caps, preceded by &lt;code&gt;$ESPANSO_&lt;/code&gt;. I pass the output through &lt;code&gt;sed&lt;/code&gt; — replacing newlines with the &lt;code&gt;&amp;gt; &lt;/code&gt; character — as to make sure that everything sticks together in the final callout.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- regex: &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;:llm\\((?P&amp;lt;userprompt&amp;gt;.*?)\\)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; replace: &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&amp;gt; [!llm]- \&amp;#34;{{prompt}}\&amp;#34; 💬\n{{output}}\n\n&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; vars:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - name: prompt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; type: shell
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; params:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cmd: &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;echo $ESPANSO_USERPROMPT | llm -m &amp;#39;gpt-4o&amp;#39; -s
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt; \ &amp;#39;Expand provided keywords to a short but effective, 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt; \ imperative one-sentence prompt in UK English.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt; \ The final output when using this prompt should be 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt; \ short and to the point.&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt; - name: output
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt; type: shell
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt; params:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt; cmd: &amp;#34;&lt;/span&gt;llm -m &amp;#39;gpt-4o&amp;#39; -s
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; \ \&amp;#34;$ESPANSO_PROMPT.\&amp;#34; | sed -z \&amp;#34;s/\\n/\\n&amp;gt; /g\&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="final-espanso-trigger"&gt;Final Espanso Trigger&lt;/h3&gt;
&lt;p&gt;The last thing we have to do is accessing our clipboard. We do this by creating a new variable inside our trigger,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- name: clipboard
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; type: clipboard
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and piping it to our final call to &lt;code&gt;llm&lt;/code&gt;. The final Espanso trigger looks as follows:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- regex: &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;:llm\\((?P&amp;lt;userprompt&amp;gt;.*?)\\)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; replace: &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&amp;gt; [!llm]- \&amp;#34;{{prompt}}\&amp;#34; 💬\n{{output}}\n\n&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; vars:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - name: clipboard
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; type: clipboard
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - name: prompt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; type: shell
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; params:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cmd: &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;echo $ESPANSO_USERPROMPT | llm -m &amp;#39;gpt-4o&amp;#39; -s
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt; \ &amp;#39;Expand provided keywords to a short but effective, 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt; \ imperative one-sentence prompt in UK English.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt; \ The final output when using this prompt should be 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt; \ short and to the point.&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt; - name: output
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt; type: shell
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt; params:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#666;font-style:italic"&gt; cmd: &amp;#34;&lt;/span&gt;echo $ESPANSO_CLIPBOARD | llm -m &amp;#39;gpt-4o&amp;#39; -s
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; \ \&amp;#34;$ESPANSO_PROMPT.\&amp;#34; | sed -z \&amp;#34;s/\\n/\\n&amp;gt; /g\&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="demonstration"&gt;Demonstration&lt;/h2&gt;
&lt;p&gt;










&lt;figure class=""&gt;

 &lt;div&gt;&lt;img loading="lazy" alt="Demonstration of LLM expansion" src=" /posts/llm-demo.gif"&gt;&lt;/div&gt;

 
 
 &lt;div class="caption-container"&gt;
 &lt;figcaption&gt; Demonstration of LLM expansion &lt;/figcaption&gt;
 &lt;/div&gt;
 
 
&lt;/figure&gt;&lt;/p&gt;</description></item><item><title>Automating Boggle</title><link>http://patrick.vanderspie.gl/posts/automating-boggle/</link><pubDate>Sat, 06 Apr 2024 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/posts/automating-boggle/</guid><description>&lt;p&gt;Last week, I had a conversation with a good friend in the spirit of the &lt;a href="https://thomasdeneuville.com/cult-of-done-manifesto/"&gt;&amp;ldquo;Cult of Done&amp;rdquo;&lt;/a&gt; (&lt;span class="llm-generated"&gt;valuing action over perfection, boldly experimenting and learning through doing&lt;/span&gt;) and &lt;a href="https://austinkleon.com/show-your-work/"&gt;sharing our work&lt;/a&gt;. Based on this conversation, I decided to get my hands dirty and attempt to create a quick and fun project, constraining myself to a couple hours of work on a Saturday morning. Key here is not worrying about perfection, but getting something out there quickly&lt;label for="sidenote-1" class="sidenote-number"&gt;&lt;/label&gt;&lt;input type="checkbox" id="sidenote-1" class="sidenote-toggle"&gt;&lt;span class="sidenote"&gt;As the goal of this experiment was to move fast, this writing is assisted using GPT-4 through the OpenAI API. Everything with a highlighted background was first written with the help of an LLM using my instructions and provided information, and rewritten and tweaked afterwards to fit my writing style.&lt;/span&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="thrifted-boggle"&gt;Thrifted Boggle&lt;/h2&gt;
&lt;p&gt;My girlfriend and I enjoy playing board and card games. Recently, we&amp;rsquo;ve picked up a copy of &lt;a href="https://en.wikipedia.org/wiki/Boggle"&gt;Boggle&lt;/a&gt; in a thrift shop. &lt;span class="llm-generated"&gt;Boggle is a word game where you try to find as many words as you can from 16 dice, each with a different letter, that are shaken in a covered tray and then set in a $4\times4$ grid. Players get three minutes to find words that are at least three letters long, and each letter in the word has to touch the letter before it in any direction. Players are not allowed to use the same letter dice more than once in a word. Once time&amp;rsquo;s up, players compare their lists and any word that appears on more than one list gets cancelled out, with players scoring points based on the length of their unique words.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;










&lt;figure class=""&gt;

 &lt;div&gt;&lt;img loading="lazy" alt="Boggle board" src=" /posts/boggle-board.jpg"&gt;&lt;/div&gt;

 
 
 &lt;div class="caption-container"&gt;
 &lt;figcaption&gt; Boggle board &lt;/figcaption&gt;
 &lt;/div&gt;
 
 
&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Our second-hand copy of Boggle has a couple of problems, however (excluding the fact that one of the dice was replaced by a Scrabble block by the previous owner). Our main problem is that the hourglass provided with our copy is broken, so we have to set up a smartphone timer. Other problems include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Counting the points afterwards takes up a lot of time, especially if we want to confirm that our words are actually on the board&lt;/li&gt;
&lt;li&gt;Confirming if a found word is an actual word takes time as well (as I love making up some plausible sounding Dutch words, looking them up in the dictionary, and claiming that I was certain that it exists if it&amp;rsquo;s not there.)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="project-goals"&gt;Project Goals&lt;/h2&gt;
&lt;p&gt;As I want to create something that both helps solve the problems above, but I also want to get something done quickly, the goal for this project is threefold:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;First, create a &lt;a href="https://telegram.org/blog/bot-revolution"&gt;Telegram bot&lt;/a&gt; that can:
&lt;ul&gt;
&lt;li&gt;Receive a picture of the shaken tray of dice&lt;/li&gt;
&lt;li&gt;Start a built-in timer to know when the round starts and ends&lt;/li&gt;
&lt;li&gt;Count our points by confirming that our words are on the board and that the words themselves exist based on a (Dutch) dictionary&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Next, I want to share my work using this blog post (in the spirit of the Cult of Done)&lt;/li&gt;
&lt;li&gt;Do all this in a couple of hours on a Saturday morning (instead of enjoying the nice Spring weather like a normal person)&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="implementation"&gt;Implementation&lt;/h2&gt;
&lt;p&gt;I started with a planning, trying to come up with the necessary sub-tasks:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Recognising labelled dice from a picture, which we need to reconstruct the grid&lt;/li&gt;
&lt;li&gt;Create a data structure that contains the allowed list of words&lt;/li&gt;
&lt;li&gt;Algorithm that traverses the grid, finding all valid words&lt;/li&gt;
&lt;li&gt;Create a Telegram bot that uses the above to act as a &amp;ldquo;referee&amp;rdquo;&lt;/li&gt;
&lt;li&gt;Write the text (that you&amp;rsquo;re currently reading) whilst doing all of the above&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="recognising-labelled-dice"&gt;Recognising labelled dice&lt;/h3&gt;
&lt;p&gt;As I am not that familiar with computer vision techniques, and I wanted to move quickly, my first attempt was to use &lt;a href="https://platform.openai.com/docs/guides/vision"&gt;GPT-4V&lt;/a&gt;, or &lt;code&gt;gpt-4-vision-preview&lt;/code&gt;, to take a picture of the Boggle grid as input and retrieve the letters from that picture as a continuous string. If this would work out, I could quickly move to the other steps of the project. I used the following prompt:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Given the image of a 4x4 grid of Boggle dice, 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;convert the letters visible on the dice into a 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;continuous 16-character string by reading from left to right,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;top to bottom. 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;For example, if the top row contains the letters &amp;#39;A&amp;#39;, &amp;#39;B&amp;#39;, &amp;#39;C&amp;#39;, &amp;#39;D&amp;#39;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;and the second row contains letters &amp;#39;E&amp;#39;, &amp;#39;F&amp;#39;, &amp;#39;G&amp;#39;, and &amp;#39;H&amp;#39;, etc., 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;your output should be &amp;#39;ABCDEFGH...etc&amp;#39;, up to the 16th letter.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Keep in mind that letters could be rotated!
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This failed miserably, however. The received output based on the image above (cropped to only display the grid of dice) was:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;The continuous 16-character string from the Boggle dice 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;is &amp;#34;INRAWMNBUDOVSOLO&amp;#34;.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Afterwards, I lost an hour trying out different things with &lt;a href="https://opencv.org/"&gt;OpenCV&lt;/a&gt; and &lt;a href="https://github.com/tesseract-ocr/tesseract"&gt;tesseract&lt;/a&gt;, but this did not seem to work out. As I still wanted to move quickly, I skipped this step and will rely on user input for the grid.&lt;/p&gt;
&lt;h3 id="recognising-valid-words"&gt;Recognising valid words&lt;/h3&gt;
&lt;p&gt;The &lt;a href="https://en.wikipedia.org/wiki/Trie"&gt;trie&lt;/a&gt; is an efficient data structure for storing large word lists. The data structure itself can be seen as a finite state machine that only accepts words used for its creation. Each node of the trie represents a prefix, with the root as the empty string. Transitions between nodes adds characters to the prefixes. &lt;span class="llm-generated"&gt;This offers quick search capabilities, therefore making it suitable for our project.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;As I&amp;rsquo;ve recently had to create an implementation of tries for other work, I simply reused this for this project. The idea behind the construction algorithm is very simple: &lt;span class="llm-generated"&gt;starting from the initial state, we check every symbol in each word. We follow transitions to states if they already exist, and create new states and transitions if they don&amp;rsquo;t. At the end of each word, we mark the last state as the final state.&lt;/span&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;def&lt;/span&gt; &lt;span style="color:#666;font-weight:bold;font-style:italic"&gt;trie&lt;/span&gt;(sequences): 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;&amp;#34;&amp;#34;Constructs a trie from given collection of sequences.&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; fsm = Automaton() 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;text-decoration:underline"&gt;for&lt;/span&gt; sequence &lt;span style="font-weight:bold"&gt;in&lt;/span&gt; sequences: 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; current = fsm.initial 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;text-decoration:underline"&gt;for&lt;/span&gt; symbol &lt;span style="font-weight:bold"&gt;in&lt;/span&gt; sequence: 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;text-decoration:underline"&gt;if&lt;/span&gt; symbol &lt;span style="font-weight:bold"&gt;not&lt;/span&gt; &lt;span style="font-weight:bold"&gt;in&lt;/span&gt; fsm.alphabet: 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; fsm.add_symbol(symbol) 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;text-decoration:underline"&gt;if&lt;/span&gt; (next_state := fsm.follow(current, symbol)) &lt;span style="font-weight:bold"&gt;is&lt;/span&gt; &lt;span style="font-weight:bold;text-decoration:underline"&gt;None&lt;/span&gt;: 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; next_state = fsm.add_state() 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; fsm.set_transition(current, next_state, symbol) 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; current = next_state 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; fsm.accepting.add(current) 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="font-weight:bold;text-decoration:underline"&gt;return&lt;/span&gt; fsm
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;words = {&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;tree&amp;#34;&lt;/span&gt;, &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;three&amp;#34;&lt;/span&gt;, &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;trie&amp;#34;&lt;/span&gt;, &lt;span style="color:#666;font-style:italic"&gt;&amp;#34;tried&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;automaton = trie(words)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;automaton.accept(&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;tree&amp;#34;&lt;/span&gt;) &lt;span style="color:#888;font-style:italic"&gt;# True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;automaton.accept(&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;tried&amp;#34;&lt;/span&gt;) &lt;span style="color:#888;font-style:italic"&gt;# True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;automton.accept(&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;thr&amp;#34;&lt;/span&gt;) &lt;span style="color:#888;font-style:italic"&gt;# False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;show(automaton)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;figure&gt;
 &lt;img src="http://patrick.vanderspie.gl/posts/trie-example.svg" alt="Example of the trie for set (tree, trie, three, tried)" class="invert-dark" loading="lazy" /&gt;
 &lt;figcaption&gt;Example of the trie for set (tree, trie, three, tried)&lt;/figcaption&gt;
&lt;/figure&gt;


&lt;p&gt;For the dictionary of valid words, I relied on the &lt;a href="https://raw.githubusercontent.com/OpenTaal/opentaal-wordlist/master/wordlist.txt"&gt;OpenTaal wordlist&lt;/a&gt;, containing over 400k Dutch words. We can shorten this list significantly by filtering out the ones that are impossible to find in Boggle:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Words that contain something other than the letters from &lt;code&gt;a&lt;/code&gt; to &lt;code&gt;z&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Words shorter than 3 letters or longer than 10 letters (as we&amp;rsquo;re usually never finding any words longer than 6, 10 is very generous)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the end, we end up with a large trie that accepts all words from our Dutch wordlist.&lt;/p&gt;
&lt;h3 id="searching-for-words-in-a-grid"&gt;Searching for words in a grid&lt;/h3&gt;
&lt;p&gt;If we have a string representing the grid as input (e.g., &lt;code&gt;&amp;quot;NTAWIRIRNBDAOASO&amp;quot;&lt;/code&gt;), we can find all possible words by &lt;span class="llm-generated"&gt;converting our grid into a graph, allowing us to utilize graph traversal algorithms to systematically search for potential word formations. This graph representation simplifies the problem into a more navigable structure where each dice is a vertex, denoted by its character. Edges between vertices are formed based on a dice&amp;rsquo;s spatial relation to its neighbours, indicating possible transitions or movements in our word formation process.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;To find all words in the grid, we can perform a depth-first traversal starting from each dice, &lt;span class="llm-generated"&gt;exploring as far as possible along each branch before backtracking. It is an ideal choice for our case here since we are interested in finding all potential paths that form words. Starting from each dice (or vertex), our DFT traces all unique paths devoid of cycles, while continuously inspecting the trie to confirm whether the traced path is leading to a valid word.&lt;/span&gt; We stop traversing further in a given path if the prefix is not present in the trie. This way, we retrieve all acyclic paths in the graph that have a path in the trie, and we don&amp;rsquo;t go deeper than necessary into the current path.&lt;/p&gt;
&lt;h3 id="telegram-bot"&gt;Telegram bot&lt;/h3&gt;
&lt;p&gt;Using the above, we can create a &lt;a href="https://core.telegram.org/bots"&gt;Telegram bot&lt;/a&gt; that uses the above to confirm our words and to keep track of our scores:&lt;/p&gt;
&lt;p&gt;










&lt;figure class=""&gt;

 &lt;div&gt;&lt;img loading="lazy" alt="Screenshot of the Telegram chat with bogglebot" src=" /posts/telegram-screenshot.PNG"&gt;&lt;/div&gt;

 
 
 &lt;div class="caption-container"&gt;
 &lt;figcaption&gt; Screenshot of the Telegram chat with &lt;code&gt;bogglebot&lt;/code&gt; &lt;/figcaption&gt;
 &lt;/div&gt;
 
 
&lt;/figure&gt;&lt;/p&gt;
&lt;span class="llm-generated"&gt;Users input their Boggle game board as a grid by invoking the &lt;code&gt;/new&lt;/code&gt; command in a chat with the bot, and the bot generates a list of all possible words by simulating all possible paths in the grid. The bot will then confirm the start and the counter of the game. During the game, the users type in the words they find, and the bot checks if the word is valid (i.e., is in the list of possible words). If the word is valid, the user&amp;rsquo;s score is incremented according to the length of the word. The score and game updates are sent back to the user in the chat. The bot is built using the &lt;code&gt;python-telegram-bot&lt;/code&gt; library, which allows easy interaction with the Telegram Bot API.&lt;/span&gt;
&lt;h2 id="possible-extensions"&gt;Possible Extensions&lt;/h2&gt;
&lt;span class="llm-generated"&gt;Given the flexibility of the implementation, there are various ways we could extend this project in the future:&lt;/span&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="llm-generated"&gt;&lt;strong&gt;Wordlist Variants:&lt;/strong&gt; Depending on our mood or the challenge we desire, we could spice up our games by introducing different wordlists for specific themes. For example, a game could be based solely on palindromes, or we could introduce a Flemish dialect-based wordlist. The possibilities and variations are endless, making each game a fresh and exciting challenge.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="llm-generated"&gt;&lt;strong&gt;Custom Time Counter:&lt;/strong&gt; A part of the thrill of Boggle comes from the time pressure. We could experiment with this element by introducing a varying time or perhaps even a countdown whereby the time decreases each round, raising the stakes progressively.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="llm-generated"&gt;&lt;strong&gt;Automatic Scoring:&lt;/strong&gt; One of the main appeals of this project is that it removes the cumbersome task of manual point counting. This could be further extended to automatically keep track of our scores across multiple games or even different days. Thus, we could concentrate on the game at hand, while the bot takes care of the statistics and progress tracking.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="llm-generated"&gt;&lt;strong&gt;Speed Chess Inspired Mode:&lt;/strong&gt; Perhaps one of the most exciting possibilities would be to create a &amp;lsquo;speed chess&amp;rsquo; inspired mode. Each player could have an individual clock, and you&amp;rsquo;d need to quickly spot and share a unique word to pause your countdown and switch turns. The game would then continue until someone&amp;rsquo;s time reaches zero. This offers the perfect blend of frantic quick-thinking, strategy, and suspense — a true test of one&amp;rsquo;s Boggle skills!&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;span class="llm-generated"&gt;In the spirit of the &amp;ldquo;Cult of Done&amp;rdquo;, I have focused on quickly getting this project up and running first in a short amount of allotted time, before worrying about enhancements or delivering the perfect project.&lt;/span&gt;</description></item><item><title>Inferno CTF — Write-Up</title><link>http://patrick.vanderspie.gl/posts/inferno-ctf-misc/</link><pubDate>Sat, 28 Dec 2019 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/posts/inferno-ctf-misc/</guid><description>&lt;p&gt;In this short write-up, we will go over two challenges in the &lt;em&gt;Misc&lt;/em&gt; category of Inferno CTF, which was hosted by &lt;a href="https://ctftime.org/team/69272"&gt;&lt;code&gt;Dc1ph3R&lt;/code&gt;&lt;/a&gt;. The challenges that we will discuss are “Color Blind” (which can be solved with a simple one-liner) and “Registering X” (which was a bit more complex). I completed these challenges with our CTF team, &lt;a href="https://ctftime.org/team/83549"&gt;&lt;code&gt;U+1F966&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="color-blind"&gt;Color Blind&lt;/h2&gt;
&lt;p&gt;In this challenge, we are provided with a &lt;code&gt;PNG&lt;/code&gt; image with a resolution of $64 \times 1$. Running &lt;code&gt;strings&lt;/code&gt;, &lt;code&gt;binwalk&lt;/code&gt;, and &lt;code&gt;foremost&lt;/code&gt; on the given file does not give us any useful information.&lt;/p&gt;
&lt;p&gt;Looking closer at this image, we can see that each pixel has a specific colour. A teammate mentioned that the actual colours of the pixels could be the key to our flag. Each pixel has a colour code that can be expressed in &lt;code&gt;RGB&lt;/code&gt; or in &lt;code&gt;HEX&lt;/code&gt;. Stringing together all the &lt;code&gt;HEX&lt;/code&gt; values is the key to obtaining our flag.&lt;/p&gt;
&lt;p&gt;Opening an image, retrieving all the &lt;code&gt;HEX&lt;/code&gt; values of the pixels, and stringing them together is a trivial task that can be done with a simple one-liner in the &lt;a href="https://julialang.org/"&gt;Julia programming language&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-Julia" data-lang="Julia"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold;text-decoration:underline"&gt;using&lt;/span&gt; FileIO, Colors
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;join(map(hex, load(&lt;span style="color:#666;font-style:italic"&gt;&amp;#34;colorblind.png&amp;#34;&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This works because images in Julia are simple arrays containing the &lt;code&gt;RGB&lt;/code&gt; value of each pixel. We map the &lt;code&gt;hex&lt;/code&gt; function (provided to us by &lt;code&gt;Colors&lt;/code&gt;) over the color values, which returns an array with &lt;code&gt;HEX&lt;/code&gt; values. We then join all the values together, which gives us the following string:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-hex" data-lang="hex"&gt;626C6168626C6168626C61685F68656C6C6F5F686F775F6172655F796F755F746F6461795F695F686F70655F796F755F6172655F6E6F745F646F696E675F746869735F6D616E75616C6C795F696E6665726E6F4354467B6833795F3130306B5F7930755F3472335F6E30375F6833785F626C316E445F3A4F7D5F646F696E675F746869735F6D616E75616C6C795F776F756C645F62655F615F6261645F696465615F796F755F73686F756C646E745F646F5F69745F6D616E75616C6C795F6F6B
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This string can probably be translated to readable text using Julia, but it was quicker to copy this output and paste it in an online &lt;em&gt;hex to string&lt;/em&gt; converter:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;blahblahblah_hello_how_are_you_today_i_hope_you_are_not_doing_this_manually_infernoCTF{h3y_100k_y0u_4r3_n07_h3x_bl1nD_:O}_doing_this_manually_would_be_a_bad_idea_you_shouldnt_do_it_manually_ok
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The output above contains the flag:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;infernoCTF{h3y_100k_y0u_4r3_n07_h3x_bl1nd_:O}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="registering-x"&gt;Registering X&lt;/h2&gt;
&lt;p&gt;The goal of this challenge was to construct a string that matches the &lt;code&gt;regex&lt;/code&gt; given to us in the challenge attachment:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-regex" data-lang="regex"&gt;infernoCTF{.(?&amp;lt;=H){21}.[a-z](?&amp;lt;=\+a){1024}[a-z][a-j](?&amp;lt;!([a-u]|[w-z])(j|[a-h])).{2,64}(?&amp;lt;!\S){255}n.{2}(?&amp;lt;=\s)g_fUn\W(?&amp;lt;=[A-z])}(?&amp;lt;=\..{14})(?&amp;lt;=^.{33})
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The given &lt;code&gt;regex&lt;/code&gt; is complex at first glance, but the challenge itself is very straightforward. We did not find a way to automate the solution of this challenge, so we solved it by hand. First, we simplified the &lt;code&gt;regex&lt;/code&gt; by removing the quantifiers after the lookbehinds, because they do not serve a purpose. Removing these quantifiers will give us an equivalent, but shorter, &lt;code&gt;regex&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-regex" data-lang="regex"&gt;infernoCTF{.(?&amp;lt;=H).[a-z](?&amp;lt;=\+a)[a-z][a-j](?&amp;lt;!([a-u]|[w-z])(j|[a-h])).{2,64}(?&amp;lt;!\S)n.{2}(?&amp;lt;=\s)g_fUn\W(?&amp;lt;=[A-z])}(?&amp;lt;=\..{14})(?&amp;lt;=^.{33})
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We start by learning about &lt;em&gt;lookbehinds&lt;/em&gt;. Positive lookbehinds (e.g, &lt;code&gt;&amp;quot;(?&amp;lt;=a)b&amp;quot;&lt;/code&gt; ) match the character after the parenthesis, but only if the character is followed by the character in the parenthesis, after the &lt;code&gt;=&lt;/code&gt;. Negative lookbehinds (e.g, &lt;code&gt;&amp;quot;(?&amp;lt;!a)b&amp;quot;&lt;/code&gt; ) match the character after the parenthesis, but only if they are not followed by the character in the parenthesis, after the &lt;code&gt;!&lt;/code&gt;. Knowing this, we can start constructing our flag.&lt;/p&gt;
&lt;p&gt;Our flag starts with &lt;code&gt;infernoCTF{&lt;/code&gt;, because the given &lt;code&gt;regex&lt;/code&gt; states that we have to match these characters literally. &lt;code&gt;.&lt;/code&gt; in our regex matches any character in our flag, so we will put an &lt;code&gt;X&lt;/code&gt; as a placeholder. We now have to match the positive lookbehind &lt;code&gt;(?&amp;lt;=H).&lt;/code&gt;, which means that our string will only match the regex when we have a character following the character &lt;code&gt;H&lt;/code&gt;. We could try adding &lt;code&gt;H+&lt;/code&gt; to our flag (making our flag &lt;code&gt;infernoCTF{XH+)&lt;/code&gt;, but this will not match the given regex. The cause of this mismatch is the fact that lookbehinds only match the character &lt;em&gt;after&lt;/em&gt; the parenthesis. It will &lt;strong&gt;not&lt;/strong&gt; match the character &lt;em&gt;in&lt;/em&gt; the parenthesis.&lt;/p&gt;
&lt;p&gt;The solution for this problem is replacing our previous &lt;code&gt;X&lt;/code&gt; with an &lt;code&gt;H&lt;/code&gt;. We now have &lt;code&gt;infernoCTF{H+&lt;/code&gt;, which matches the first part of our &lt;code&gt;regex&lt;/code&gt;. The rest of the &lt;code&gt;regex&lt;/code&gt; follows the same principle: we have a bunch of lookbehinds that force us to precede a character with another character. Around those lookbehinds we have more common &lt;code&gt;regex&lt;/code&gt; symbols that make it possible to match the character in the parenthesis. Now that we got the gist of the challenge, we will quickly go over the solution:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;infernoCTF{&lt;/code&gt; forces us to start our flag with &lt;code&gt;infernoCTF{&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.(?&amp;lt;=H).[a-z](?&amp;lt;=\+a)&lt;/code&gt; forces us to add &lt;code&gt;H+a&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[a-z][a-j](?&amp;lt;!([a-u]|[w-z)(j|[a-h])).{2,64}&lt;/code&gt; makes us add &lt;code&gt;vi&lt;/code&gt; to our flag, followed by an unspecified amount (between two and sixty-four, which will be constrained later in the &lt;code&gt;regex&lt;/code&gt;) of placeholder characters&lt;/li&gt;
&lt;li&gt;&lt;code&gt;(?&amp;lt;!\S)n&lt;/code&gt; forces us to add an &lt;code&gt;n&lt;/code&gt; after a whitespace character&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.{2}(?&amp;lt;=\s)g&lt;/code&gt; forces us to add a &lt;code&gt;g&lt;/code&gt; after a whitespace character&lt;/li&gt;
&lt;li&gt;&lt;code&gt;_fUn&lt;/code&gt; forces us to add &lt;code&gt;_fUn&lt;/code&gt; to our flag&lt;/li&gt;
&lt;li&gt;&lt;code&gt;\W(?&amp;lt;=[A-z])}&lt;/code&gt; forces us to add a &lt;code&gt;}&lt;/code&gt; after a non-word character between &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;z&lt;/code&gt; in the ASCII table (e.g., &lt;code&gt;]&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;(?&amp;lt;=\..{14})&lt;/code&gt; forces us to count fourteen characters back and add a &lt;code&gt;.&lt;/code&gt;. We can safely put our &lt;code&gt;.&lt;/code&gt; in the collection of unspecified characters mentioned in the third step above.&lt;/p&gt;
&lt;p&gt;The last part of our &lt;code&gt;regex&lt;/code&gt; forces us to make the flag exactly thirty-three characters long. This can be achieved by adding or removing a bunch of unspecified characters (which were mentioned in the same third step). One of the possible solutions is &lt;code&gt;infernoCTF{H+avi . ng no g_fUn]}&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Because of a lack of knowledge about tools that generate strings based on given &lt;code&gt;regex&lt;/code&gt; (&lt;em&gt;that also support lookbehinds!&lt;/em&gt;), we decided to solve this challenge by hand. Although it is a bit of tedious work, it certainly is possible to construct the flag manually.&lt;/p&gt;</description></item><item><title>About</title><link>http://patrick.vanderspie.gl/about/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/about/</guid><description>&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Website created using the &lt;a href="https://gohugo.io/"&gt;Hugo&lt;/a&gt; static site generator.&lt;/li&gt;
&lt;li&gt;Main font of this website is &lt;a href="https://github.com/iaolo/iA-Fonts/tree/master/iA%20Writer%20Quattro"&gt;iA Writer Quattro&lt;/a&gt;, header titles use &lt;a href="https://osp.kitchen/foundry/alfphabet/"&gt;Alfphabet&lt;/a&gt;, code blocks use &lt;a href="https://github.com/subframe7536/maple-font"&gt;Maple Mono&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;</description></item><item><title>Blog — Patrick Van der Spiegel</title><link>http://patrick.vanderspie.gl/blog/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/blog/</guid><description/></item><item><title>Orange Red Iron Glaze #000</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/000/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/000/</guid><description>








 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 0&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-0" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-0"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="0"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #001</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/001/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/001/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 1&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-1" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-1"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="1"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;1%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="1" style="white-space: nowrap;"&gt;1&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #002</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/002/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/002/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 2&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-2" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-2"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="2"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #003</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/003/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/003/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 3&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-3" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-3"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="3"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;3%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="3" style="white-space: nowrap;"&gt;3&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #004</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/004/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/004/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 4&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-4" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-4"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="4"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #005</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/005/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/005/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 5&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-5" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-5"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="5"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;5%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="5" style="white-space: nowrap;"&gt;5&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #006</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/006/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/006/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 6&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-6" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-6"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="6"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;6%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="6" style="white-space: nowrap;"&gt;6&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #007</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/007/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/007/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 7&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-7" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-7"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="7"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="7" style="white-space: nowrap;"&gt;7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #008</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/008/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/008/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 8&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-8" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-8"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="8"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;8%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="8" style="white-space: nowrap;"&gt;8&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #009</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/009/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/009/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 9&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-9" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-9"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="9"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="9" style="white-space: nowrap;"&gt;9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #010</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/010/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/010/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 10&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-10" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-10"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="10"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;10%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="10" style="white-space: nowrap;"&gt;10&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #011</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/011/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/011/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 11&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-11" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-11"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="11"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11" style="white-space: nowrap;"&gt;11&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #012</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/012/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/012/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 12&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-12" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-12"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="12"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;12%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="12" style="white-space: nowrap;"&gt;12&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #013</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/013/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/013/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 13&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-13" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-13"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="13"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;13%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="13" style="white-space: nowrap;"&gt;13&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #014</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/014/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/014/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 14&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-14" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-14"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="14"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;14%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="14" style="white-space: nowrap;"&gt;14&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #015</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/015/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/015/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 15&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-15" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-15"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="15"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #016</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/016/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/016/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 16&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-16" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-16"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="16"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16" style="white-space: nowrap;"&gt;16&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #017</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/017/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/017/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 17&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-17" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-17"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="17"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;17%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="17" style="white-space: nowrap;"&gt;17&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #018</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/018/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/018/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 18&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-18" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-18"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="18"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;18%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="18" style="white-space: nowrap;"&gt;18&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #019</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/019/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/019/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 19&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-19" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-19"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="19"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;19%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="19" style="white-space: nowrap;"&gt;19&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #020</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/020/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/020/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 20&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-20" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-20"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="20"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;50.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="50.7" style="white-space: nowrap;"&gt;50.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #021</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/021/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/021/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 21&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-21" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-21"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="21"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;50.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="50.7" style="white-space: nowrap;"&gt;50.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;1%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="1" style="white-space: nowrap;"&gt;1&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #022</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/022/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/022/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 22&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-22" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-22"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="22"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;50.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="50.7" style="white-space: nowrap;"&gt;50.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #023</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/023/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/023/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 23&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-23" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-23"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="23"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;50.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="50.7" style="white-space: nowrap;"&gt;50.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;3%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="3" style="white-space: nowrap;"&gt;3&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #024</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/024/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/024/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 24&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-24" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-24"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="24"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;50.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="50.7" style="white-space: nowrap;"&gt;50.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #025</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/025/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/025/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 25&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-25" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-25"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="25"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;50.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="50.7" style="white-space: nowrap;"&gt;50.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;5%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="5" style="white-space: nowrap;"&gt;5&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #026</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/026/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/026/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 26&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-26" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-26"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="26"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;50.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="50.7" style="white-space: nowrap;"&gt;50.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;6%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="6" style="white-space: nowrap;"&gt;6&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #027</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/027/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/027/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 27&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-27" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-27"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="27"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;50.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="50.7" style="white-space: nowrap;"&gt;50.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="7" style="white-space: nowrap;"&gt;7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #028</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/028/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/028/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 28&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-28" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-28"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="28"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;50.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="50.7" style="white-space: nowrap;"&gt;50.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;8%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="8" style="white-space: nowrap;"&gt;8&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #029</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/029/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/029/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 29&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-29" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-29"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="29"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;50.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="50.7" style="white-space: nowrap;"&gt;50.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="9" style="white-space: nowrap;"&gt;9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #030</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/030/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/030/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 30&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-30" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-30"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="30"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;50.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="50.7" style="white-space: nowrap;"&gt;50.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;10%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="10" style="white-space: nowrap;"&gt;10&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #031</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/031/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/031/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 31&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-31" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-31"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="31"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;50.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="50.7" style="white-space: nowrap;"&gt;50.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11" style="white-space: nowrap;"&gt;11&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #032</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/032/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/032/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 32&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-32" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-32"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="32"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;50.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="50.7" style="white-space: nowrap;"&gt;50.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;12%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="12" style="white-space: nowrap;"&gt;12&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #033</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/033/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/033/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 33&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-33" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-33"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="33"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;50.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="50.7" style="white-space: nowrap;"&gt;50.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;13%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="13" style="white-space: nowrap;"&gt;13&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #034</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/034/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/034/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 34&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-34" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-34"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="34"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;50.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="50.7" style="white-space: nowrap;"&gt;50.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;14%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="14" style="white-space: nowrap;"&gt;14&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #035</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/035/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/035/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 35&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-35" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-35"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="35"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;50.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="50.7" style="white-space: nowrap;"&gt;50.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #036</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/036/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/036/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 36&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-36" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-36"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="36"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;50.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="50.7" style="white-space: nowrap;"&gt;50.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16" style="white-space: nowrap;"&gt;16&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #037</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/037/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/037/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 37&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-37" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-37"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="37"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;50.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="50.7" style="white-space: nowrap;"&gt;50.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;17%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="17" style="white-space: nowrap;"&gt;17&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #038</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/038/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/038/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 38&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-38" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-38"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="38"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;50.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="50.7" style="white-space: nowrap;"&gt;50.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;18%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="18" style="white-space: nowrap;"&gt;18&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #039</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/039/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/039/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 39&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-39" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-39"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="39"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;50.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="50.7" style="white-space: nowrap;"&gt;50.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;19%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="19" style="white-space: nowrap;"&gt;19&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #040</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/040/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/040/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 40&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-40" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-40"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="40"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;20.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="20.9" style="white-space: nowrap;"&gt;20.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #041</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/041/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/041/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 41&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-41" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-41"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="41"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;20.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="20.9" style="white-space: nowrap;"&gt;20.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;1%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="1" style="white-space: nowrap;"&gt;1&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #042</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/042/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/042/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 42&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-42" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-42"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="42"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;20.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="20.9" style="white-space: nowrap;"&gt;20.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #043</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/043/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/043/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 43&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-43" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-43"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="43"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;20.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="20.9" style="white-space: nowrap;"&gt;20.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;3%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="3" style="white-space: nowrap;"&gt;3&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #044</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/044/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/044/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 44&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-44" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-44"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="44"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;20.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="20.9" style="white-space: nowrap;"&gt;20.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #045</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/045/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/045/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 45&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-45" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-45"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="45"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;20.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="20.9" style="white-space: nowrap;"&gt;20.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;5%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="5" style="white-space: nowrap;"&gt;5&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #046</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/046/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/046/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 46&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-46" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-46"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="46"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;20.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="20.9" style="white-space: nowrap;"&gt;20.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;6%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="6" style="white-space: nowrap;"&gt;6&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #047</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/047/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/047/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 47&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-47" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-47"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="47"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;20.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="20.9" style="white-space: nowrap;"&gt;20.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="7" style="white-space: nowrap;"&gt;7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #048</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/048/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/048/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 48&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-48" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-48"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="48"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;20.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="20.9" style="white-space: nowrap;"&gt;20.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;8%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="8" style="white-space: nowrap;"&gt;8&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #049</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/049/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/049/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 49&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-49" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-49"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="49"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;20.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="20.9" style="white-space: nowrap;"&gt;20.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="9" style="white-space: nowrap;"&gt;9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #050</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/050/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/050/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 50&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-50" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-50"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="50"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;20.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="20.9" style="white-space: nowrap;"&gt;20.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;10%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="10" style="white-space: nowrap;"&gt;10&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #051</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/051/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/051/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 51&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-51" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-51"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="51"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;20.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="20.9" style="white-space: nowrap;"&gt;20.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11" style="white-space: nowrap;"&gt;11&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #052</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/052/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/052/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 52&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-52" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-52"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="52"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;20.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="20.9" style="white-space: nowrap;"&gt;20.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;12%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="12" style="white-space: nowrap;"&gt;12&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #053</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/053/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/053/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 53&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-53" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-53"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="53"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;20.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="20.9" style="white-space: nowrap;"&gt;20.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;13%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="13" style="white-space: nowrap;"&gt;13&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #054</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/054/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/054/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 54&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-54" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-54"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="54"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;20.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="20.9" style="white-space: nowrap;"&gt;20.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;14%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="14" style="white-space: nowrap;"&gt;14&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #055</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/055/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/055/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 55&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-55" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-55"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="55"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;20.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="20.9" style="white-space: nowrap;"&gt;20.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #056</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/056/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/056/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 56&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-56" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-56"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="56"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;20.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="20.9" style="white-space: nowrap;"&gt;20.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16" style="white-space: nowrap;"&gt;16&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #057</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/057/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/057/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 57&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-57" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-57"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="57"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;20.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="20.9" style="white-space: nowrap;"&gt;20.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;17%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="17" style="white-space: nowrap;"&gt;17&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #058</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/058/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/058/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 58&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-58" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-58"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="58"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;20.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="20.9" style="white-space: nowrap;"&gt;20.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;18%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="18" style="white-space: nowrap;"&gt;18&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #059</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/059/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/059/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 59&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-59" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-59"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="59"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;20.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="20.9" style="white-space: nowrap;"&gt;20.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzeroxide (natuurlijk)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;19%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="19" style="white-space: nowrap;"&gt;19&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #060</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/060/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/060/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 60&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-60" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-60"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="60"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #061</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/061/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/061/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 61&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-61" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-61"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="61"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzer (synthetisch)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;1%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="1" style="white-space: nowrap;"&gt;1&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #062</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/062/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/062/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 62&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-62" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-62"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="62"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzer (synthetisch)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #063</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/063/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/063/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 63&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-63" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-63"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="63"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzer (synthetisch)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;3%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="3" style="white-space: nowrap;"&gt;3&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #064</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/064/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/064/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 64&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-64" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-64"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="64"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzer (synthetisch)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #065</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/065/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/065/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 65&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-65" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-65"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="65"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzer (synthetisch)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;5%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="5" style="white-space: nowrap;"&gt;5&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #066</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/066/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/066/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 66&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-66" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-66"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="66"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzer (synthetisch)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;6%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="6" style="white-space: nowrap;"&gt;6&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #067</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/067/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/067/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 67&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-67" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-67"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="67"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzer (synthetisch)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="7" style="white-space: nowrap;"&gt;7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #068</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/068/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/068/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 68&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-68" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-68"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="68"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzer (synthetisch)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;8%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="8" style="white-space: nowrap;"&gt;8&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #069</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/069/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/069/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 69&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-69" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-69"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="69"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzer (synthetisch)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="9" style="white-space: nowrap;"&gt;9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #070</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/070/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/070/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 70&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-70" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-70"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="70"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzer (synthetisch)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;10%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="10" style="white-space: nowrap;"&gt;10&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #071</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/071/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/071/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 71&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-71" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-71"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="71"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzer (synthetisch)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11" style="white-space: nowrap;"&gt;11&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #072</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/072/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/072/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 72&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-72" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-72"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="72"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzer (synthetisch)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;12%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="12" style="white-space: nowrap;"&gt;12&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #073</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/073/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/073/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 73&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-73" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-73"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="73"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzer (synthetisch)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;13%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="13" style="white-space: nowrap;"&gt;13&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #074</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/074/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/074/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 74&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-74" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-74"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="74"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzer (synthetisch)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;14%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="14" style="white-space: nowrap;"&gt;14&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #075</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/075/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/075/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 75&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-75" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-75"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="75"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzer (synthetisch)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #076</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/076/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/076/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 76&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-76" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-76"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="76"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzer (synthetisch)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16" style="white-space: nowrap;"&gt;16&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #077</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/077/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/077/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 77&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-77" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-77"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="77"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzer (synthetisch)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;17%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="17" style="white-space: nowrap;"&gt;17&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #078</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/078/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/078/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 78&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-78" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-78"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="78"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzer (synthetisch)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;18%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="18" style="white-space: nowrap;"&gt;18&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 
 
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze #079</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/079/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/079/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;div class="recipe-table" style="display: block; width: 100%;"&gt;
 &lt;h3&gt;Recipe 79&lt;/h3&gt;

 &lt;div class="recipe-input-container" style="
 margin-bottom: 1em;
 padding: 0.6em 1em;
 background-color: #1a1a1a;
 border-radius: 6px;
 display: flex;
 align-items: center;
 justify-content: center;
 gap: 0.4em;
 flex-wrap: wrap;
 width: 100%;
 box-sizing: border-box;
 "&gt;
 &lt;label for="recipe-grams-79" style="
 margin: 0;
 font-weight: normal;
 color: #cccccc;
 font-size: 14px;
 "&gt;Hoeveelheid glazuur:&lt;/label&gt;
 &lt;input
 type="number"
 id="recipe-grams-79"
 class="recipe-grams-input"
 value="100"
 min="1"
 step="1"
 style="
 width: 70px;
 padding: 0.3em 0.5em;
 border: 1px solid #444;
 background-color: #000;
 color: #fff;
 border-radius: 4px;
 font-size: 14px;
 text-align: center;
 "
 &gt;
 &lt;span style="margin: 0; color: #cccccc; font-size: 14px;"&gt;gram&lt;/span&gt;
 &lt;/div&gt;

 &lt;div style="overflow-x: auto; width: 100%; display: block; clear: both;"&gt;
 &lt;table style="width: 100%; margin-top: 0; min-width: 280px; display: table;"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="white-space: normal; word-wrap: break-word;"&gt;Ingredient&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;%&lt;/th&gt;
 &lt;th style="white-space: nowrap;"&gt;Gram&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody class="recipe-tbody" data-recipe-id="79"&gt;
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaliveldspaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;46.7%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="46.7" style="white-space: nowrap;"&gt;46.7&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kaolien&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Bentoniet&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;2%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="2" style="white-space: nowrap;"&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Beenderas&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;15%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="15" style="white-space: nowrap;"&gt;15&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Lithiumcarbonaat&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="4" style="white-space: nowrap;"&gt;4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Talk&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;16.9%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="16.9" style="white-space: nowrap;"&gt;16.9&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Kwarts&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;11.4%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="11.4" style="white-space: nowrap;"&gt;11.4&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;td style="white-space: normal; word-wrap: break-word;"&gt;Rood ijzer (synthetisch)&lt;/td&gt;
 &lt;td style="white-space: nowrap;"&gt;19%&lt;/td&gt;
 &lt;td class="recipe-grams" data-percentage="19" style="white-space: nowrap;"&gt;19&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 
 
 


&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
 
 function updateRecipeGrams(input) {
 const totalGrams = parseFloat(input.value) || 100;
 const recipeId = input.id.replace('recipe-grams-', '');
 const tbody = document.querySelector('.recipe-tbody[data-recipe-id="' + recipeId + '"]');

 if (tbody) {
 const gramsCells = tbody.querySelectorAll('.recipe-grams');
 gramsCells.forEach(function(cell) {
 const percentage = parseFloat(cell.getAttribute('data-percentage'));
 const grams = (percentage / 100) * totalGrams;
 
 cell.textContent = grams.toFixed(2) + ' g';
 });
 }
 }

 
 const inputs = document.querySelectorAll('.recipe-grams-input');
 inputs.forEach(function(input) {
 
 updateRecipeGrams(input);

 
 input.addEventListener('input', function() {
 updateRecipeGrams(this);
 });
 });
});
&lt;/script&gt;</description></item><item><title>Orange Red Iron Glaze Mixes</title><link>http://patrick.vanderspie.gl/ceramics/or-glaze/999/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/ceramics/or-glaze/999/</guid><description/></item><item><title>Running</title><link>http://patrick.vanderspie.gl/running/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>http://patrick.vanderspie.gl/running/</guid><description>








 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 






 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


&lt;div class="running-container"&gt;

 &lt;div class="running-image"&gt;
 &lt;img src="http://patrick.vanderspie.gl/images/running.png" alt="Daily running visualization" loading="lazy" class="invert-dark"&gt;
 &lt;/div&gt;

 
 
 
 
 
 
 &lt;div class="running-table-wrapper"&gt;
 &lt;table class="running-table"&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th scope="col"&gt;Year&lt;/th&gt;
 
 &lt;th scope="col"&gt;Distance by 11&amp;nbsp;August&lt;/th&gt;
 &lt;th scope="col" title="2026 minus that year"&gt;Change&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 
 
 
 
 
 
 &lt;tr class="running-row--current"&gt;
 &lt;th scope="row"&gt;2026&lt;/th&gt;
 &lt;td class="running-distance"&gt;468 km&lt;/td&gt;
 &lt;td class="running-change"&gt;&lt;span class="change change--none"&gt;—&lt;/span&gt;&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;th scope="row"&gt;2025&lt;/th&gt;
 &lt;td class="running-distance"&gt;454 km&lt;/td&gt;
 &lt;td class="running-change"&gt;
 &lt;span class="change change--up"&gt;+14 km&lt;/span&gt;&lt;/td&gt;
 &lt;/tr&gt;
 
 
 
 
 
 
 
 &lt;tr&gt;
 &lt;th scope="row"&gt;2024&lt;/th&gt;
 &lt;td class="running-distance"&gt;704 km&lt;/td&gt;
 &lt;td class="running-change"&gt;
 &lt;span class="change change--down"&gt;−236 km&lt;/span&gt;&lt;/td&gt;
 &lt;/tr&gt;
 
 
 &lt;/tbody&gt;
 &lt;/table&gt;
 &lt;/div&gt;
 

 
 &lt;div class="running-timestamp"&gt;
 &lt;span class="timestamp-label"&gt;Last updated:&lt;/span&gt;
 &lt;span class="timestamp-value"&gt;12 August 2026, 03:05 UTC&lt;/span&gt;
 &lt;/div&gt;
 
&lt;/div&gt;

&lt;style&gt;
.running-table-wrapper {
 margin-top: 0.5em;
 overflow-x: auto;
}

.running-table {
 
 display: table;
 
 width: 62.23%;
 max-width: 100%;
 margin: 0 auto;
 border-collapse: collapse;
 font-size: 0.9em;
 line-height: 1.4;
}

.running-table th,
.running-table td {
 border: none;
 border-bottom: 1px solid var(--code-border);
 padding: 0.45em 1.1em;
 text-align: center;
 white-space: nowrap;
}

.running-table thead th {
 font-size: 0.75em;
 font-weight: 600;
 letter-spacing: 0.06em;
 text-transform: uppercase;
 color: var(--content-secondary);
 
 white-space: normal;
 vertical-align: bottom;
}

.running-table tbody th {
 font-weight: 400;
 color: var(--content-secondary);
}

.running-table tbody tr:last-child th,
.running-table tbody tr:last-child td {
 border-bottom: none;
}

.running-table .running-distance {
 color: var(--content-primary);
}

.running-table .running-distance,
.running-table .running-change {
 font-variant-numeric: tabular-nums;
}

.running-table .running-row--current th,
.running-table .running-row--current td {
 font-weight: 600;
 color: var(--content-primary);
}

.change--up {
 color: #4caf50;
}

.change--down {
 color: #e53935;
}

.change--flat,
.change--none {
 color: var(--content-secondary);
}

.running-container {
 max-width: 100%;
 
 margin: 0.5em auto 2em;
 display: flex;
 flex-direction: column;
 gap: 0;
}

.running-image {
 width: 100%;
 display: flex;
 justify-content: center;
 
 padding-right: 7.04%;
 
 overflow: hidden;
}

.running-image img {
 width: 100%;
 height: auto;
 display: block;
 
 margin-top: -7.3%;
}

.running-timestamp {
 margin-top: 2em;
 text-align: center;
 font-size: 0.8em;
 color: #999;
}

.timestamp-label {
 margin-right: 0.3em;
 font-weight: 600;
}

.timestamp-value {
 font-style: italic;
}

@media (prefers-color-scheme: dark) {
 .running-timestamp { color: #666; }
}

.dark .running-timestamp { color: #666; }
.light .running-timestamp { color: #999; }

 
@media (max-width: 768px) {
 .running-container {
 margin: 0.25em auto 1em;
 }

 .running-timestamp {
 font-size: 0.8em;
 }

 
 .running-table th,
 .running-table td {
 padding: 0.45em 0.6em;
 }
}
&lt;/style&gt;
</description></item></channel></rss>