<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Artifact Shelf</title>
  <subtitle>A shelf of small interactive web artifacts: simulations, explainers, generative art, games and toys. Each one is a single HTML file you can run, read and keep.</subtitle>
  <link href="https://dogum.github.io/artifact-shelf/"/>
  <link rel="self" href="https://dogum.github.io/artifact-shelf/feed.xml"/>
  <id>https://dogum.github.io/artifact-shelf/</id>
  <updated>2026-10-10T12:00:00Z</updated>
  <author><name>Greg</name><uri>https://github.com/dogum</uri></author>
  <entry>
    <title>Electric Fire</title>
    <link href="https://dogum.github.io/artifact-shelf/a/electric-fire/"/>
    <id>https://dogum.github.io/artifact-shelf/a/electric-fire/</id>
    <published>2026-10-10T12:00:00Z</published>
    <updated>2026-10-10T12:00:00Z</updated>
    <category term="Simulations"/>
    <summary>Lightning and thunder computed from the physics: a leader grown through the electric field, the return stroke, and thunder built from the bolt&#39;s shape.</summary>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://dogum.github.io/artifact-shelf/media/electric-fire/poster.webp&quot; alt=&quot;&quot; width=&quot;640&quot;/&gt;&lt;/p&gt;&lt;p&gt;Lightning and thunder computed from the physics: a leader grown through the electric field, the return stroke, and thunder built from the bolt&amp;#39;s shape.&lt;/p&gt;&lt;p&gt;A scrolling film of one lightning flash, told over a night sky that stays pinned behind the page. Each caption moves the camera and replays one stage of the flash: the cloud charging, the stepped leader feeling its way down, the attachment, the return stroke and the thunder. Every bolt is grown from the electric field by the dielectric breakdown model, and the thunder you hear is synthesised from that bolt&amp;#39;s own shape and your distance from it. The title is from Franklin&amp;#39;s 1752 letter on the kite: &amp;quot;the pointed wire will draw the electric fire from them&amp;quot;.&lt;/p&gt;
&lt;h2 id=&quot;how-to-use-it&quot;&gt;How to use it&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;The title sky&lt;/strong&gt; strikes on its own about 7 km away, with a field-mill readout in the corner and a scale bar. &lt;strong&gt;Turn on sound&lt;/strong&gt; plays the rain and the thunder after its true delay, and &lt;strong&gt;Strike now&lt;/strong&gt; starts a flash.&lt;/li&gt;&lt;li&gt;Scroll to walk through one flash. &lt;strong&gt;01 A cloud charges itself&lt;/strong&gt; shows the charge centres and the field at the ground. &lt;strong&gt;02 Feeling its way down&lt;/strong&gt; grows the stepped leader at ×700, with &lt;strong&gt;Show the field&lt;/strong&gt; to draw the equipotentials and &lt;strong&gt;Grow another&lt;/strong&gt;. &lt;strong&gt;03 Who gets struck&lt;/strong&gt; zooms in on a tower, with the striking-distance circle and the upward leader, and names what was hit; &lt;strong&gt;Again&lt;/strong&gt; replays it.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;04 The flash runs upward&lt;/strong&gt; plays the return stroke and the dart leaders that follow it. &lt;strong&gt;Slow it down ×160,000&lt;/strong&gt; makes the return stroke a visible wave. &lt;strong&gt;05 Thunder, read from the bolt&lt;/strong&gt; colours the channel by when its sound reaches you, with a &lt;strong&gt;How far away&lt;/strong&gt; slider (0.5 to 20 km) and the length of the thunder. &lt;strong&gt;06 The kite and the key&lt;/strong&gt; tells the 1752 experiments with Franklin&amp;#39;s kite in the scene.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;07 Your storm&lt;/strong&gt; is the instrument deck. &lt;strong&gt;Strike&lt;/strong&gt;, &lt;strong&gt;Storm on its own&lt;/strong&gt; for automatic flashes, or &lt;strong&gt;tap the sky&lt;/strong&gt; to start a leader there. Sliders set &lt;strong&gt;Branching η&lt;/strong&gt;, &lt;strong&gt;Peak current&lt;/strong&gt;, &lt;strong&gt;Strokes&lt;/strong&gt;, &lt;strong&gt;Distance&lt;/strong&gt; and &lt;strong&gt;Air temperature&lt;/strong&gt;. &lt;strong&gt;Speed&lt;/strong&gt; picks &lt;strong&gt;Real time&lt;/strong&gt;, &lt;strong&gt;×700&lt;/strong&gt; or &lt;strong&gt;×160,000&lt;/strong&gt;. &lt;strong&gt;On the ground&lt;/strong&gt; toggles the &lt;strong&gt;Tower&lt;/strong&gt;, &lt;strong&gt;House&lt;/strong&gt; and &lt;strong&gt;Tree&lt;/strong&gt;, and &lt;strong&gt;Show&lt;/strong&gt; adds the &lt;strong&gt;Field&lt;/strong&gt;, &lt;strong&gt;Sound map&lt;/strong&gt; or &lt;strong&gt;Striking distance&lt;/strong&gt;. Gauges report what was struck, the leader steps, the main channel length, the striking distance, the flash-to-thunder delay and how long the thunder lasts, beside a 30-second field-mill trace and the computed thunder waveform.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Lightning in a block&lt;/strong&gt; grows a Lichtenberg figure in a slab of acrylic. &lt;strong&gt;Branching η&lt;/strong&gt; changes the fronds, &lt;strong&gt;Charge a new block&lt;/strong&gt; starts again, and &lt;strong&gt;Classic model&lt;/strong&gt; switches to the 1984 set-up and measures the fractal dimension live.&lt;/li&gt;&lt;/ul&gt;
&lt;h2 id=&quot;how-it-works&quot;&gt;How it works&lt;/h2&gt;
&lt;p&gt;The leader grows by the dielectric breakdown model of Niemeyer, Pietronero and Wiesmann (1984), on a vertical slice of air 2.4 km wide and 1.8 km tall in 20 m cells. The cloud base at 1.26 km is held at the cloud&amp;#39;s potential, and the ground, tower, house and tree at zero. The potential is relaxed by SOR each time the channel grows, warm-started from the last solution. Each step goes to one of the eight neighbouring cells with odds proportional to (potential drop / distance)^η, and the channel counts as a conductor that loses some potential along its length. When the lowest tip comes within the striking distance r = 10·I^0.65 m of the ground or a grounded object, that point grows an upward leader by the same rule, and the flash attaches where the two meet.&lt;/p&gt;
&lt;p&gt;For drawing, each 20 m step is split into eight kinked pieces and given a random wander in depth. The leader front comes down at 1.5 × 10⁵ m/s. The return stroke climbs from the struck point at 10⁸ m/s, and each branch carries current in proportion to the square root of the channel below it. A flash has three or four strokes 30 to 150 ms apart, the later ones led down the main channel by dart leaders. A stroke&amp;#39;s light is a sum of decays from 40 µs to 40 ms, integrated over each frame&amp;#39;s exposure. The bolt is drawn as instanced ribbons into a half-float target with a six-level bloom. One bloom level doubles as a light map, so each flash lights the cloud base, the rain and the ground of a procedural storm scene.&lt;/p&gt;
&lt;p&gt;The thunder is built in a Web Worker from the same bolt. Every piece of channel sends out a short N-wave, loudest at right angles to the piece, falling off as 1/r and arriving after its own distance divided by the speed of sound at the chosen air temperature. Air absorption removes the high frequencies with distance. Sound from low down is cut beyond the refraction shadow zone, √(2Rz) with R ≈ 88 km for air cooling 6.5 K per km. A few dozen ground echoes are added. The field mill sums three charge centres (+40 C at 10 km, −40 C at 6 km, +4 C at 2 km) and their images, plus the fair-weather field. Each flash drains part of the negative charge, which rebuilds over tens of seconds. The Lichtenberg block solves Poisson&amp;#39;s equation with a uniform trapped charge and a grounded rim and channels.&lt;/p&gt;
&lt;h2 id=&quot;notes&quot;&gt;Notes&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;The Checks table is computed in the page: the speed of sound at 20 °C against the &amp;quot;3 seconds per kilometre&amp;quot; rule; the peak current whose striking distance matches the 45.7 m rolling sphere of IEEE 998 and NFPA 780; the edge of the thunder shadow zone, about 30 km, against thunder rarely being heard beyond about 25 km; the fractal dimension of the classic model, about 1.7 at η = 1 as in 1984; and the thunder&amp;#39;s peak frequency against Few (1969) and Glassner (2000).&lt;/li&gt;&lt;li&gt;The leader is grown in a two-dimensional slice, and its wander in depth is random, as the page states.&lt;/li&gt;&lt;li&gt;The sky needs WebGL2 with floating-point render targets. Without it the page shows a notice, and the Lichtenberg block, the timeline and most of the Checks table still work.&lt;/li&gt;&lt;li&gt;The history runs from Franklin&amp;#39;s kite, Dalibard&amp;#39;s rod at Marly-la-Ville and Richmann&amp;#39;s death in 1753 to Lichtenberg&amp;#39;s figures of 1777 and Schonland and Collens&amp;#39;s photographs of the stepped leader in 1934, with a twelve-item source list.&lt;/li&gt;&lt;li&gt;This copy fixes three things in the original. Without WebGL2 the script stopped partway, so the Lichtenberg block, the Checks table and the timeline stayed empty; they now load. Each frame reset the frame clock after its own work, so the storm ran about a tenth slower than real time; it now keeps time. And a leftover build note is gone from the footer.&lt;/li&gt;&lt;li&gt;It also fixes six smaller things. Thunder already on its way now plays if you turn on sound before it arrives, including from earlier flashes. Changing the distance or air temperature after a flash replaces the thunder you hear, not only the waveform. The Checks table compares the first thunder with the distance it was computed for. And with reduced motion set in the system, nothing strikes on its own: flashes start from &lt;strong&gt;Strike now&lt;/strong&gt;, &lt;strong&gt;Again&lt;/strong&gt; or the lab, and the Lichtenberg block waits for a tap. And the &lt;strong&gt;Peak current&lt;/strong&gt; slider starts at the 30 kA its label shows; it sat at about 24 kA. And the block&amp;#39;s &lt;strong&gt;Branching η&lt;/strong&gt; now applies to a block that hasn&amp;#39;t been struck yet.&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <title>A Great Variety of Colours</title>
    <link href="https://dogum.github.io/artifact-shelf/a/great-variety-of-colours/"/>
    <id>https://dogum.github.io/artifact-shelf/a/great-variety-of-colours/</id>
    <published>2026-10-09T12:00:00Z</published>
    <updated>2026-10-09T12:00:00Z</updated>
    <category term="Simulations"/>
    <summary>A live soap film and soap bubble whose colours come from exact thin-film optics, as the film drains, turns black and bursts.</summary>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://dogum.github.io/artifact-shelf/media/great-variety-of-colours/poster.webp&quot; alt=&quot;&quot; width=&quot;640&quot;/&gt;&lt;/p&gt;&lt;p&gt;A live soap film and soap bubble whose colours come from exact thin-film optics, as the film drains, turns black and bursts.&lt;/p&gt;&lt;p&gt;A long scrolling explainer on why soap films are coloured, built around a live soap film and bubble. Light reflects from the film&amp;#39;s front and its back, the two reflections interfere, and which colours survive depends only on the thickness, so the colours are a map of the film as it drains, thins to black and bursts. Every colour on the page is computed from the reflected spectrum, and the film itself is a small fluid model running on the GPU. The title is Newton&amp;#39;s phrase from &lt;em&gt;Opticks&lt;/em&gt; (1704).&lt;/p&gt;
&lt;h2 id=&quot;how-to-use-it&quot;&gt;How to use it&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;The title bubble&lt;/strong&gt; drifts on its own, its colours swirling as it drains. &lt;strong&gt;Tap&lt;/strong&gt; it to pop it. It also pops by itself once its black cap grows, and a new one inflates.&lt;/li&gt;&lt;li&gt;The contents bar jumps to &lt;strong&gt;I Two reflections&lt;/strong&gt;, &lt;strong&gt;II Draining&lt;/strong&gt;, &lt;strong&gt;III Black film&lt;/strong&gt;, &lt;strong&gt;IV Bursting&lt;/strong&gt;, &lt;strong&gt;V Lamps &amp;amp; angles&lt;/strong&gt;, &lt;strong&gt;VI Lab&lt;/strong&gt; and &lt;strong&gt;Notes&lt;/strong&gt;.&lt;/li&gt;&lt;li&gt;From I onward a film on a wire frame stays pinned beside the text, with the light and a &lt;strong&gt;film age&lt;/strong&gt; clock above it. Its toolbar has &lt;strong&gt;Measure&lt;/strong&gt; (tap the film to read the thickness and reflected colour there), &lt;strong&gt;Stir&lt;/strong&gt;, &lt;strong&gt;Blow&lt;/strong&gt; and &lt;strong&gt;Pop&lt;/strong&gt;, which change what a drag or tap on the film does, a &lt;strong&gt;True colour&lt;/strong&gt; / &lt;strong&gt;Thickness map&lt;/strong&gt; switch, &lt;strong&gt;New film&lt;/strong&gt; and &lt;strong&gt;Pause&lt;/strong&gt;.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;I&lt;/strong&gt; holds the film as a perfect wedge, thin at the top, so it reads like a ruler. &lt;strong&gt;Film thickness&lt;/strong&gt; (0 to 1,200 nm) drives a two-wave diagram, the reflected spectrum and the colour seen, and a computed strip lines up with Newton&amp;#39;s 1704 list of the colour sequence.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;II&lt;/strong&gt; lets the film drain, with an average-thickness readout and &lt;strong&gt;New film&lt;/strong&gt;. &lt;strong&gt;III&lt;/strong&gt; follows the black film as it spreads, with its share of the area and how much light it reflects. &lt;strong&gt;IV&lt;/strong&gt; pops the film and replays the burst 500 times slower, with the rim speed in micrometre film and in black film, and a &lt;strong&gt;Replay&lt;/strong&gt; button.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;V&lt;/strong&gt; switches the light between &lt;strong&gt;Daylight&lt;/strong&gt;, &lt;strong&gt;Sodium lamp&lt;/strong&gt;, &lt;strong&gt;Tungsten&lt;/strong&gt; and &lt;strong&gt;RGB LED&lt;/strong&gt;, and &lt;strong&gt;Viewing angle&lt;/strong&gt; (0° to 80°) tilts the line of sight.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;VI Lab&lt;/strong&gt; opens everything: &lt;strong&gt;Time-lapse&lt;/strong&gt; (0.5× to 8×), &lt;strong&gt;Glycerol&lt;/strong&gt; for slower draining, &lt;strong&gt;Air humidity&lt;/strong&gt; (10 to 95%), &lt;strong&gt;Viewing angle&lt;/strong&gt;, a &lt;strong&gt;Vertical (drains)&lt;/strong&gt; or &lt;strong&gt;Horizontal (no draining)&lt;/strong&gt; film, &lt;strong&gt;Common black film&lt;/strong&gt; or &lt;strong&gt;Newton black film&lt;/strong&gt;, and the four lights.&lt;/li&gt;&lt;/ul&gt;
&lt;h2 id=&quot;how-it-works&quot;&gt;How it works&lt;/h2&gt;
&lt;p&gt;Colour comes from a table built when the page loads. For each thickness from 0 to 3,200 nm and each viewing angle up to 80°, the Airy formula for a free film gives the reflectance with all its multiple reflections, for both polarisations, at 81 wavelengths from 380 to 780 nm. Water&amp;#39;s refractive index follows n(λ) = 1.324 + 3046/λ² with λ in nm. The reflected spectrum is multiplied by the light source and the CIE 1931 colour-matching functions and converted to linear sRGB, with the brightest reflection, about 8% at a quarter-wave thickness, shown as white. The CIE tables and the D65 and A illuminants are embedded in the page, and the sodium lamp is a single line at 589.3 nm. Each light gets its own 2048 × 12 table texture, so the shader looks up every pixel&amp;#39;s colour from its thickness and angle.&lt;/p&gt;
&lt;p&gt;The film is a reduced model, and the page says so. It is a two-dimensional sheet of incompressible fluid, solved on the GPU with stable fluids and MacCormack advection of the thickness in half-float textures, 168 × 220 cells on a desktop and 120 × 156 on small screens. Thinner film weighs less, so buoyancy measured against the local mean thickness lifts thin film and sinks thick film. The thickness changes through gravity drainage, with a flux that grows as the cube of the thickness, slow evaporation set by the humidity, and marginal regeneration along the side wires, where thin film is pulled out of the thick meniscus and rises in plumes. Below 45 nm a cell jumps to black film, common or Newton, and black film spreads into neighbouring film that is thin enough. A hole spreads cell by cell at the Taylor–Culick speed √(2γ/ρh) with γ = 30 mN/m, so it races through the thinnest film. The burst in the frame is shown 500 times slower and the bubble&amp;#39;s 150 times.&lt;/p&gt;
&lt;p&gt;The title bubble runs the same model on a latitude–longitude grid and is drawn as a sphere, with front and back reflections of a studio environment.&lt;/p&gt;
&lt;h2 id=&quot;notes&quot;&gt;Notes&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;The Model notes at the foot of the page include a validation table computed live in the page: first-order red, the Michel-Lévy &amp;quot;sensitive tint&amp;quot;, against a 206 nm film; the sodium fringe spacing λ/2n against 221 nm; the quarter-wave reflectance against 7.8%; a 10 nm black film against about 0.20%; and the rim speed in 1 µm film against 7.7 m/s. The notes add that a soap film in white light at normal incidence shows the colours of the Michel-Lévy chart at a retardation of 2nh, which served as an independent check of the colour engine.&lt;/li&gt;&lt;li&gt;The colours for any thickness are exact. The draining is a reduced model with sliders standing in for real recipes, as the page states.&lt;/li&gt;&lt;li&gt;The films need WebGL2 with floating-point render targets. Without them a notice takes the place of each film.&lt;/li&gt;&lt;li&gt;The timeline &lt;strong&gt;Three centuries of bubbles&lt;/strong&gt; and the page&amp;#39;s source list run from Hooke&amp;#39;s &lt;em&gt;Micrographia&lt;/em&gt; (1665) and Newton&amp;#39;s &lt;em&gt;Opticks&lt;/em&gt; through Young, Plateau, Boys, Perrin, Mysels, Taylor and Culick, to Kellay, Wu and Goldburg&amp;#39;s soap-film experiments and the IUPAC definitions of the two black films.&lt;/li&gt;&lt;li&gt;This copy fixes two things in the original. Each frame reset the frame clock after its own work, so on a slow GPU the draining, evaporation and the bubble&amp;#39;s life ran slower than real time; they now keep time. And a swipe that started on the title bubble popped it; it now pops on a tap.&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <title>Belousov&#39;s Clock</title>
    <link href="https://dogum.github.io/artifact-shelf/a/belousovs-clock/"/>
    <id>https://dogum.github.io/artifact-shelf/a/belousovs-clock/</id>
    <published>2026-10-09T12:00:00Z</published>
    <updated>2026-10-09T12:00:00Z</updated>
    <category term="Simulations"/>
    <summary>The Belousov–Zhabotinsky reaction, run live from the Oregonator equations: a chemical clock, waves you tap and cut into spirals, and spirals in the heart.</summary>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://dogum.github.io/artifact-shelf/media/belousovs-clock/poster.webp&quot; alt=&quot;&quot; width=&quot;640&quot;/&gt;&lt;/p&gt;&lt;p&gt;The Belousov–Zhabotinsky reaction, run live from the Oregonator equations: a chemical clock, waves you tap and cut into spirals, and spirals in the heart.&lt;/p&gt;&lt;p&gt;A long-form explainer on the Belousov–Zhabotinsky reaction, the mixture of bromate, malonic acid, sulfuric acid and an iron indicator that turns from red to blue and back on a steady beat. It runs from Belousov&amp;#39;s 1951 result, which editors turned down for six years, through the three-reaction clock, travelling waves and spiral waves, to the heart, where the same spirals drive some arrhythmias. The dishes, the flask and the charts are all computed in the browser from the Oregonator equations, and a tap on any dish starts a wave.&lt;/p&gt;
&lt;h2 id=&quot;how-to-use-it&quot;&gt;How to use it&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;The contents bar under the title jumps to &lt;strong&gt;I The rejection&lt;/strong&gt;, &lt;strong&gt;II The clock&lt;/strong&gt;, &lt;strong&gt;III–V Waves, spirals, hearts&lt;/strong&gt;, &lt;strong&gt;VI Lab&lt;/strong&gt; and &lt;strong&gt;VII Fine print&lt;/strong&gt;.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;The title dish&lt;/strong&gt; starts on its own: it fires a ring, cuts it, and the loose ends wind up into a spiral pair. &lt;strong&gt;Tap&lt;/strong&gt; to start a wave and &lt;strong&gt;drag&lt;/strong&gt; across a wave to break it. Left alone, it fires a new wave at a random spot now and then.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;II The clock&lt;/strong&gt; is the stirred version. &lt;strong&gt;Pause&lt;/strong&gt;, &lt;strong&gt;Faster&lt;/strong&gt; and &lt;strong&gt;Slower&lt;/strong&gt; control the flask&amp;#39;s time-lapse, the &lt;strong&gt;A Brake&lt;/strong&gt;, &lt;strong&gt;B Runaway&lt;/strong&gt; and &lt;strong&gt;C Reset&lt;/strong&gt; cards light up in turn, and the reaction network, the concentration traces and the phase plane all follow the same solution. Drag &lt;strong&gt;Stoichiometric factor f&lt;/strong&gt; between 0.2 and 3.0 and the status line says whether the flask has to oscillate or gets stuck red or blue.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;III to V&lt;/strong&gt; pin a dish beside the text (above it on a phone) and play one scene per card as you scroll: a single ring with its measured front speed, colliding waves, two competing pacemakers, a broken wave, the phase view, a meandering tip, then the heart with its sinus node, reentry, fibrillation and a defibrillating flash. &lt;strong&gt;Replay&lt;/strong&gt; restarts a scene and &lt;strong&gt;Flash again&lt;/strong&gt; repeats the shock.&lt;/li&gt;&lt;li&gt;The toolbar under that dish has &lt;strong&gt;Wave / cut&lt;/strong&gt; (tap or drag), &lt;strong&gt;Light&lt;/strong&gt; (hold to add bromide and block waves; it reads &lt;strong&gt;Bromide&lt;/strong&gt; unless the view is Ruthenium), &lt;strong&gt;Pacemaker&lt;/strong&gt; (tap to add or remove one) and &lt;strong&gt;Probe&lt;/strong&gt; (tap to place an electrode that draws a trace and reads the period, or beats per minute in heart units). The menu switches the view between &lt;strong&gt;Ferroin&lt;/strong&gt;, &lt;strong&gt;Cerium&lt;/strong&gt;, &lt;strong&gt;Ruthenium&lt;/strong&gt;, &lt;strong&gt;Phase&lt;/strong&gt; and &lt;strong&gt;HBrO₂&lt;/strong&gt;. &lt;strong&gt;Tips&lt;/strong&gt; marks each spiral tip with its +1 or −1 charge and a trail, and &lt;strong&gt;Pause&lt;/strong&gt; and &lt;strong&gt;Clear&lt;/strong&gt; stop and wipe the dish.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;VI Lab&lt;/strong&gt; unlocks everything: &lt;strong&gt;Bromide per reset, f&lt;/strong&gt; (1.0 to 2.2), &lt;strong&gt;Time-scale ratio, ε&lt;/strong&gt; (0.02 to 0.09), &lt;strong&gt;Light / bromide, φ&lt;/strong&gt; (0 to 0.05), &lt;strong&gt;Playback speed&lt;/strong&gt;, &lt;strong&gt;New pacemaker period&lt;/strong&gt;, &lt;strong&gt;Units&lt;/strong&gt; (&lt;strong&gt;BZ dish&lt;/strong&gt; or &lt;strong&gt;Heart tissue&lt;/strong&gt;) and seven presets from &lt;strong&gt;Spiral pair&lt;/strong&gt; to &lt;strong&gt;Oscillatory dish&lt;/strong&gt;.&lt;/li&gt;&lt;/ul&gt;
&lt;h2 id=&quot;how-it-works&quot;&gt;How it works&lt;/h2&gt;
&lt;p&gt;The chemistry follows the Field–Kőrös–Noyes (FKN) mechanism, reduced to the three processes the page calls Brake, Runaway and Reset: bromide removes bromous acid, HBrO₂ (A); once bromide falls below a critical level, HBrO₂ makes more of itself and oxidises the catalyst (B); the oxidised catalyst reacts with malonic acid and bromomalonic acid and releases fresh bromide (C). The flask integrates the Oregonator, Field and Noyes&amp;#39;s model of that mechanism, in its two-variable form: ε dx/dτ = x(1 − x) − f z (x − q)/(x + q) and dz/dτ = x − z, where x is scaled HBrO₂, z is the oxidised catalyst, and bromide is fast enough to sit at its steady state y = f z/(q + x). The rate constants are the textbook values measured for the cerium reaction, with 0.06 M bromate and 0.02 M malonic acid, which give ε ≈ 0.0099, q ≈ 7.6×10⁻⁵ and a time unit of 50 s. Each step of 5×10⁻⁴ time units solves the stiff x equation by backward Euler with Newton iterations and relaxes z exactly. The network diagram weights each of the model&amp;#39;s five reactions by its live rate, and the f slider&amp;#39;s verdict comes from the trace and determinant of the Jacobian at the fixed point.&lt;/p&gt;
&lt;p&gt;An unstirred layer is an excitable medium. At rest it is stable, but a large enough push of HBrO₂ fires a pulse, and the spot stays refractory until the catalyst is reduced again; diffusion between neighbours turns that into travelling waves. The dishes solve the reaction–diffusion form of the Oregonator in Tyson–Fife scaling, with the light-driven bromide term of Krug, Pohlmann and Kuhnert: ε ∂u/∂t = u − u² − (f v + φ)(u − q)/(u + q) + ∇²u and ∂v/∂t = u − v, with f = 1.4, q = 0.002, ε = 0.02 and φ = 0.01 by default. The grid is 512 × 512 (Δx = 0.4) inside a circular no-flux wall, stepped in WebGL2 fragment shaders that ping-pong between two 32-bit float textures (16-bit where that is all the GPU offers). Each step takes three Newton iterations of backward Euler on the stiff u reaction, adds diffusion through an isotropic nine-point Laplacian, and relaxes v exactly; the catalyst itself does not diffuse. Steps are at most ε/4, which is 0.005 at the defaults. A third channel holds local bromide from the light tool and the flash, which spreads and decays. One time unit is about 50 s and one length unit about 0.32 mm, so the dish is about 6.2 cm across and 1× playback is a 60× time-lapse. &lt;strong&gt;Heart tissue&lt;/strong&gt; rescales the same pattern to a conduction speed of 0.5 m/s and a 0.18 s spiral period.&lt;/p&gt;
&lt;p&gt;Gestures write straight into the grid. A tap sets u to 0.9 in a small disc, well above threshold. A drag paints a stripe where u drops below its resting value and v rises to 0.34, an artificial refractory band, so a front crossing it is cut and its two free ends curl into spirals turning in opposite directions. A pacemaker repeats a tap at a fixed period. Spiral tips are found on the GPU: each point&amp;#39;s phase is the angle of (log u, v) around a reference point, the winding of that phase around every grid square flags a singularity, and a Newton solve on the bilinear interpolant places the tip inside its square. The tips are read back, matched from frame to frame into trails and counted by sign. The probe and the card readouts sample single points of the grid: front speed comes from the arrival times at two points 30 length units apart, periods from successive upswings of the oxidised catalyst.&lt;/p&gt;
&lt;p&gt;The picture is transmitted light. The reduced and oxidised forms of each catalyst get their own absorbance, so ferroin goes from red to blue, cerium from clear to yellow and the ruthenium catalyst from orange to green, with a meniscus at the glass, a light box that dims toward the rim and a little film grain. The phase view colours each point by its place in the cycle, and the HBrO₂ view maps log u onto an inferno ramp. Each dish pauses when it scrolls out of view or the tab is hidden, and with reduced motion set the title dish runs at half speed and adds no waves of its own.&lt;/p&gt;
&lt;h2 id=&quot;notes&quot;&gt;Notes&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;The history and the examples in &lt;strong&gt;The same spirals, elsewhere&lt;/strong&gt; come with an eleven-item source list at the foot of the page, from Belousov&amp;#39;s 1959 abstract and the 1972 FKN paper to Winfree&amp;#39;s &lt;em&gt;When Time Breaks Down&lt;/em&gt;. The four thumbnails in that section are illustrations, drawn once as rigid spirals and rotated.&lt;/li&gt;&lt;li&gt;Simplifications the page states: the dish uses q = 0.002, larger than the textbook value, and leaves out convection, CO₂ bubbles and oxygen effects. The flask uses the cerium rate constants and is drawn in ferroin colours, which the page notes behave similarly.&lt;/li&gt;&lt;li&gt;The dishes need WebGL2 with floating-point render targets. Without them a notice takes the place of each dish.&lt;/li&gt;&lt;li&gt;This copy fixes two things in the original. The dishes timed each step from the end of the previous frame, so on a slow GPU the model crawled (in software rendering the scroll-section dish now covers about 30 times more model time per second); and without WebGL2 the page stopped before drawing the flask, timeline, charts and thumbnails, which now draw on their own.&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <title>Grand Complication Atlas</title>
    <link href="https://dogum.github.io/artifact-shelf/a/grand-complication-atlas/"/>
    <id>https://dogum.github.io/artifact-shelf/a/grand-complication-atlas/</id>
    <published>2026-10-09T12:00:00Z</published>
    <updated>2026-10-09T12:00:00Z</updated>
    <category term="Explainers"/>
    <summary>A working 3D model of a grand complication pocket watch that keeps real time from its own escapement, with a tourbillon, perpetual calendar and chimes.</summary>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://dogum.github.io/artifact-shelf/media/grand-complication-atlas/poster.webp&quot; alt=&quot;&quot; width=&quot;640&quot;/&gt;&lt;/p&gt;&lt;p&gt;A working 3D model of a grand complication pocket watch that keeps real time from its own escapement, with a tourbillon, perpetual calendar and chimes.&lt;/p&gt;&lt;p&gt;A working 3D model of a grand complication pocket watch, Calibre A-1, laid out like a horological drawing and taken apart over twelve plates. It is modelled on the published figures of Vacheron Constantin&amp;#39;s Les Cabinotiers Berkley Grand Complication, shown in 2024. The Berkley&amp;#39;s gear layout has not been published, so the movement here is an original design, but every ratio in it is real. When the page opens, the hands are set to your local time, the calendar to today and the moon to tonight&amp;#39;s phase. From then on the escapement keeps the time: every hand and indication is driven through the gear train from the beats of the balance, and nothing reads the device clock to point them.&lt;/p&gt;
&lt;h2 id=&quot;how-to-use-it&quot;&gt;How to use it&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Drag&lt;/strong&gt; to turn the watch over, &lt;strong&gt;pinch&lt;/strong&gt; or &lt;strong&gt;scroll&lt;/strong&gt; to zoom, and &lt;strong&gt;tap&lt;/strong&gt; any part for a card with its tooth count, speed and job. Numbered callouts match the parts list.&lt;/li&gt;&lt;li&gt;The plate panel on the right (a bottom sheet on phones) steps through &lt;strong&gt;I to XII&lt;/strong&gt; with &lt;strong&gt;‹ ›&lt;/strong&gt; or the numerals: the watch, its eleven layers, the mainspring, the going train, the escapement, the balance, the tourbillon, the motion works, the perpetual calendar, the moon phase, the minute repeater, and a closing plate that sets the model beside the Berkley. Each plate moves the camera and shows live readouts such as watch time, beats since midnight, balance amplitude and power reserve. A plate can be linked directly with &lt;code&gt;#plate1&lt;/code&gt; to &lt;code&gt;#plate12&lt;/code&gt;.&lt;/li&gt;&lt;li&gt;The dock at the bottom sets the time rate: &lt;strong&gt;1/100&lt;/strong&gt;, &lt;strong&gt;1/10&lt;/strong&gt;, &lt;strong&gt;1×&lt;/strong&gt;, &lt;strong&gt;1 min/s&lt;/strong&gt;, &lt;strong&gt;1 h/s&lt;/strong&gt; and &lt;strong&gt;1 day/s&lt;/strong&gt;. &lt;strong&gt;Back to now&lt;/strong&gt; runs the train forward or back to real time.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Explode&lt;/strong&gt; spreads the eleven layers along their arbors, and &lt;strong&gt;Layers&lt;/strong&gt; hides or isolates each one, with &lt;strong&gt;Show all&lt;/strong&gt; to bring them back. &lt;strong&gt;Sound off&lt;/strong&gt; turns the chimes on.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;The mainspring&lt;/strong&gt; plate has &lt;strong&gt;Hold to wind&lt;/strong&gt;: the crown, winding pinion, crown wheel, ratchet and click turn, the spring coils redraw, and the balance swings wider. Left alone the watch runs down and stops.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;The perpetual calendar&lt;/strong&gt; plate has buttons that jump to the end of February in 2027, 2028 and 2100, and &lt;strong&gt;Back to today&lt;/strong&gt;.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;The minute repeater&lt;/strong&gt; plate has &lt;strong&gt;Strike the time&lt;/strong&gt;, a &lt;strong&gt;Chimes in passing&lt;/strong&gt; choice of &lt;strong&gt;Off&lt;/strong&gt;, &lt;strong&gt;Hours&lt;/strong&gt; or &lt;strong&gt;Westminster&lt;/strong&gt;, and &lt;strong&gt;Night silence 22:00–08:00&lt;/strong&gt;.&lt;/li&gt;&lt;/ul&gt;
&lt;h2 id=&quot;how-it-works&quot;&gt;How it works&lt;/h2&gt;
&lt;p&gt;The going train runs from the mainspring barrel (80 teeth) through the centre wheel (pinion 10, wheel 80) and third wheel (pinion 10, wheel 75) to the tourbillon cage, which is the fourth wheel. Inside the cage, the escape pinion (8 leaves) rolls round a fixed 80-tooth wheel. The cage turns once a minute, and its blue arrow is the seconds hand. The balance beats at 18,000 vibrations an hour. Its phase follows real time, each zero crossing releases the escape wheel by 12°, and every wheel, hand and indication is computed from that beat count through the tooth ratios. On its plate the escapement runs at 1/100 speed, with a live Locked, Unlocking, Impulse or Drop readout. The balance amplitude falls as the power reserve runs down from 60 hours.&lt;/p&gt;
&lt;p&gt;The perpetual calendar is driven by a 24-hour wheel. Date, day and month stars advance through jumpers, and a 48-month program cam sets each month&amp;#39;s length by the depth of its notch. Like a real perpetual calendar, it follows the four-year rule, so in 2100 it shows a 29 February that the Gregorian calendar skips. The moon phase is geared from the 24-hour wheel through 8/56 and 16/135, which gives 59.0625 days per turn of a two-moon disc, about a day of error in 122 years.&lt;/p&gt;
&lt;p&gt;The minute repeater reads the time from an hour snail with 12 steps, a quarter snail and a minute snail with four lobes of 15 steps. Racks fall on them, and five hammers strike five gongs while a governor sets the pace. The strikes are synthesised with Web Audio. The model is drawn with three.js: about 290 meshes and 146 parts, with gear teeth cut when the page loads.&lt;/p&gt;
&lt;h2 id=&quot;notes&quot;&gt;Notes&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;The closing plate compares the model with the Berkley and lists its sources. The movement layout, the parts and the name Calibre A-1 belong to this model, not to the Berkley.&lt;/li&gt;&lt;li&gt;The model needs WebGL. Without it the page says so and suggests a current browser with hardware acceleration on.&lt;/li&gt;&lt;li&gt;The page remembers the last plate you opened.&lt;/li&gt;&lt;li&gt;This copy fixes two things in the original. In live mode the hands were copied from the device clock on every frame, although the page says the gears move them; the watch now runs on its own escapement and is set to your clock only when the page opens and when you come back to a hidden tab. And returning to a plate with a fixed rate (such as the 60× going train) while the hands were still travelling back to now could leave it running live at 1×; a fixed-rate plate now always sets its rate.&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <title>Kármán&#39;s Street</title>
    <link href="https://dogum.github.io/artifact-shelf/a/karmans-street/"/>
    <id>https://dogum.github.io/artifact-shelf/a/karmans-street/</id>
    <published>2026-10-09T12:00:00Z</published>
    <updated>2026-10-09T12:00:00Z</updated>
    <category term="Simulations"/>
    <summary>Vortex shedding and the Kármán vortex street, run in a live lattice-Boltzmann wind tunnel that measures its own drag, lift and Strouhal number.</summary>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://dogum.github.io/artifact-shelf/media/karmans-street/poster.webp&quot; alt=&quot;&quot; width=&quot;640&quot;/&gt;&lt;/p&gt;&lt;p&gt;Vortex shedding and the Kármán vortex street, run in a live lattice-Boltzmann wind tunnel that measures its own drag, lift and Strouhal number.&lt;/p&gt;&lt;p&gt;A long scrolling explainer on vortex shedding: above a Reynolds number of about 47 the wake behind a cylinder stops being symmetric and throws off eddies from alternate sides, which settle into the staggered double row called a Kármán vortex street. The page follows it from creeping flow at Re = 1 through the onset of the swing, the Strouhal number, the forces on the body, wires that sing in the wind, cloud streets behind an island and a stalled wing. Every flow picture is a lattice-Boltzmann wind tunnel running live on the GPU, and the meters under it read drag, lift and shedding frequency off the running simulation.&lt;/p&gt;
&lt;h2 id=&quot;how-to-use-it&quot;&gt;How to use it&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;The title tunnel&lt;/strong&gt; opens on a cylinder at Re = 150 that is already shedding, shown as smoke streaks and surface dye. &lt;strong&gt;Drag&lt;/strong&gt; across it to draw solid obstacles into the flow, and &lt;strong&gt;Reset tunnel&lt;/strong&gt; clears them and starts the cylinder again. The corner readout gives the Reynolds and Strouhal numbers.&lt;/li&gt;&lt;li&gt;The contents bar under it jumps to &lt;strong&gt;I Reynolds&lt;/strong&gt;, &lt;strong&gt;II Strouhal&lt;/strong&gt;, &lt;strong&gt;III Forces&lt;/strong&gt;, &lt;strong&gt;IV Sound&lt;/strong&gt;, &lt;strong&gt;V Sky&lt;/strong&gt;, &lt;strong&gt;VI Wings&lt;/strong&gt;, &lt;strong&gt;VII Lab&lt;/strong&gt; and &lt;strong&gt;Notes&lt;/strong&gt;.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;I to VII&lt;/strong&gt; pin a second tunnel beside the text (above it on a phone), with four meters (&lt;strong&gt;Reynolds&lt;/strong&gt;, &lt;strong&gt;Drag Cd&lt;/strong&gt;, &lt;strong&gt;Lift Cl&lt;/strong&gt;, &lt;strong&gt;Strouhal&lt;/strong&gt;) and a scrolling trace of drag and lift. Each card loads its own scene as it reaches the middle of the screen, and &lt;strong&gt;Replay&lt;/strong&gt; restarts the scenes in I and V.&lt;/li&gt;&lt;li&gt;The toolbar under that tunnel has &lt;strong&gt;Draw&lt;/strong&gt; and &lt;strong&gt;Erase&lt;/strong&gt; (drag on the tunnel), a view menu with &lt;strong&gt;Smoke&lt;/strong&gt;, &lt;strong&gt;Vorticity&lt;/strong&gt;, &lt;strong&gt;Speed&lt;/strong&gt;, &lt;strong&gt;Pressure&lt;/strong&gt; and &lt;strong&gt;Clouds&lt;/strong&gt;, &lt;strong&gt;Pause&lt;/strong&gt; (it then reads &lt;strong&gt;Play&lt;/strong&gt;) and &lt;strong&gt;Restart flow&lt;/strong&gt;, which restarts the flow around whatever is in the tunnel.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;I&lt;/strong&gt; runs Re = 1, where the smoke closes up behind the cylinder; Re = 20, with the two trapped eddies and a live eddy-length readout; Re = 100 started from a tiny nudge, with a log-scale chart of the lift growing and levelling off and the measured growth per cycle; and the street at Re = 150, with von Kármán&amp;#39;s 1911 stability result and Bénard&amp;#39;s films from three years earlier.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;II&lt;/strong&gt; has a &lt;strong&gt;Reynolds number&lt;/strong&gt; slider from 50 to 200 that changes the running flow, and plots each settled measurement against Williamson&amp;#39;s fit to experiments. &lt;strong&gt;III&lt;/strong&gt; draws lift against drag as a figure of eight, since drag pulses twice per shedding cycle, with the mean drag and lift amplitude beside it.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;IV&lt;/strong&gt; picks a wire, &lt;strong&gt;Power line&lt;/strong&gt;, &lt;strong&gt;Guy wire&lt;/strong&gt; or &lt;strong&gt;Car aerial&lt;/strong&gt;, and gives its diameter, wind speed, tone and Reynolds number. &lt;strong&gt;Play the tone&lt;/strong&gt; plays that frequency until you press &lt;strong&gt;Stop&lt;/strong&gt;. The card also covers Strouhal&amp;#39;s 1878 experiments with whirled wires, helical strakes on chimneys, and why the 1940 Tacoma Narrows collapse was flutter rather than shedding.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;V&lt;/strong&gt; puts a model of Guadalupe Island, 260 km off Baja California, in the &lt;strong&gt;Clouds&lt;/strong&gt; view. &lt;strong&gt;VI&lt;/strong&gt; loads a NACA 0012 wing at Re = 1,000 based on chord, and &lt;strong&gt;Angle of attack&lt;/strong&gt; (0° to 30°) tilts it in the running flow while the card reports mean lift and drag.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;VII Lab&lt;/strong&gt; opens everything: &lt;strong&gt;Reynolds number&lt;/strong&gt; (1 to 3,000 on a log scale), &lt;strong&gt;Playback speed&lt;/strong&gt; (0.25× to 3×), eight presets (&lt;strong&gt;Cylinder&lt;/strong&gt;, &lt;strong&gt;Square&lt;/strong&gt;, &lt;strong&gt;Flat plate&lt;/strong&gt;, &lt;strong&gt;Two in a row&lt;/strong&gt;, &lt;strong&gt;Side by side&lt;/strong&gt;, &lt;strong&gt;Airfoil&lt;/strong&gt;, &lt;strong&gt;Island&lt;/strong&gt;, &lt;strong&gt;Empty&lt;/strong&gt;), &lt;strong&gt;Write a word into the wind&lt;/strong&gt; with &lt;strong&gt;Place word&lt;/strong&gt; (up to ten letters, set as solid type), and &lt;strong&gt;Smoke rake&lt;/strong&gt; and &lt;strong&gt;Surface dye&lt;/strong&gt; to switch the two kinds of smoke on and off.&lt;/li&gt;&lt;/ul&gt;
&lt;h2 id=&quot;how-it-works&quot;&gt;How it works&lt;/h2&gt;
&lt;p&gt;The flow is computed with the lattice Boltzmann method on a D2Q9 lattice. Each cell holds nine particle populations that stream to their neighbours and relax toward a local equilibrium, and on average this reproduces the incompressible Navier–Stokes equations at low Mach number. The collision is regularized BGK after Latt and Chopard: the non-equilibrium part of each population is rebuilt from the local momentum flux before relaxing, which filters out modes that are not hydrodynamic. The Reynolds number sets the viscosity through ν = UL/Re and the relaxation time τ = 3ν + ½, with an inlet speed U of 0.1 lattice units (Mach 0.17) and L the cylinder diameter, the wing&amp;#39;s chord or the frontal height of whatever has been drawn. A Smagorinsky eddy viscosity, solved in closed form from the same momentum flux, is added to τ with a constant of 0.1, rising to 0.15 between Re = 500 and 3,000.&lt;/p&gt;
&lt;p&gt;The desktop tunnel is 768 × 288 cells with the cylinder 24 across (544 × 192 and 16 across on small screens, and 272 × 96 with a &lt;code&gt;?lite&lt;/code&gt; query string), so it is 12 diameters tall and shows 28 diameters of length. The inlet column is held at equilibrium with uniform velocity, the top and bottom walls are free-slip (populations reflect specularly), solids use half-way bounce-back, and the outlet is zero-gradient. The last 96 columns are a hidden sponge layer where τ rises quadratically, so vortices are damped before they reach the exit. Each lattice step is one fragment-shader pass in WebGL2 that pulls the nine populations from the neighbouring cells, collides them and writes them through multiple render targets to three 32-bit float textures, ping-ponging between two sets; the spare channels carry density and velocity for the other passes. Every restart puts a small upward velocity in the upper half of the near wake to break the symmetry, 10% of the inflow speed in most scenes and 0.3% in the onset scene so the growth can be followed from a tiny amplitude.&lt;/p&gt;
&lt;p&gt;Forces come from the momentum-exchange method. A shader adds up 2·fᵢ·cᵢ over every link from a fluid cell into a solid one, repeated passes sum 4 × 4 blocks until only a few texels are left, and one readback per frame gives the drag and lift coefficients F/(½ρU²L). The Strouhal number comes from the upward zero crossings of the lift about its mean over the last eight or so periods, interpolated between samples, as St = L/(UT); it is shown only when successive periods agree within 5%, and the meters read settling or steady otherwise. The eddy length in I.2 reads back the centreline velocity and finds the last cell of reversed flow behind the cylinder, and the onset chart takes the growth per cycle from the peaks of the lift while it is still small. The frame loop uses an adaptive step budget: 18 lattice steps per frame at 1× (12 on small screens), cut by 15% after a run of frames slower than 26 ms down to a floor of 4, and raised one step at a time when frames take under 18 ms. A new scene also fast-forwards a few thousand steps, spread over frames at up to five times the budget, so the wake has formed by the time the card is read.&lt;/p&gt;
&lt;p&gt;For display, a second pass computes vorticity by central differences (scaled by D/U), speed, and the pressure coefficient from the density. &lt;strong&gt;Vorticity&lt;/strong&gt; colours clockwise spin coral and counter-clockwise blue, &lt;strong&gt;Speed&lt;/strong&gt; maps the speed onto a navy-to-cream ramp and darkens reversed flow, and &lt;strong&gt;Pressure&lt;/strong&gt; is a diverging map of the pressure coefficient. The smoke lives in two half-float textures advected semi-Lagrangian by the lattice velocity: one channel is a rake of streaks fed in at the inlet, and two hold dye released from cells touching a solid, coral above the body&amp;#39;s centroid and blue below. The rake is pre-filled across the whole tunnel on every restart so the first frame already shows streamlines. &lt;strong&gt;Smoke&lt;/strong&gt; draws the dye over a faint vorticity field, &lt;strong&gt;Clouds&lt;/strong&gt; draws it white over a dark sea, and solids are drawn as brushed metal with a lit rim. The wire tones use f = 0.2·U/D (80 Hz for the 25 mm power line in a 10 m/s wind, 333 Hz for the 6 mm guy wire, 1,000 Hz for the car aerial at 90 km/h) and are synthesised with Web Audio as a sine at f, a quieter sine at 2f, a slow 0.7 Hz tremolo and white noise band-passed around f. Each tunnel stops when it scrolls out of view or the tab is hidden, and with reduced motion set the title tunnel runs at half speed and skips the fast-forward.&lt;/p&gt;
&lt;h2 id=&quot;notes&quot;&gt;Notes&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;The Model notes at the foot of the page include a validation table for the desktop grid against published values. Drag is 2.32 at Re 20 and 1.74 at Re 40 against Fornberg&amp;#39;s 2.00 and 1.50; the eddy length is 1.00 D and 2.33 D against Coutanceau and Bouard&amp;#39;s 0.93 D and 2.13 D; shedding starts between Re 45 and 55 against about 47; the Strouhal number is 0.141 at Re 55 and 0.173 at Re 100 against 0.130 and 0.164 from Williamson&amp;#39;s fit; and at Re 100 the mean drag is 1.49 and the lift amplitude 0.40 against about 1.33 and 0.33 from 2D simulations. The cylinder blocks 8% of the tunnel&amp;#39;s height, and the page notes that drag, lift and frequency run high for that reason, as they do in a real wind tunnel before blockage corrections. The notes also report a check against a separate CPU implementation of the same scheme, with the fields agreeing to 10⁻⁶.&lt;/li&gt;&lt;li&gt;The tunnel is a two-dimensional slice. Real cylinder wakes turn three-dimensional above Re ≈ 190, while this one keeps drawing a clean street, and it cannot show how helical strakes, introduced in 1957, stop chimneys shaking by making vortices leave at different moments along the height.&lt;/li&gt;&lt;li&gt;The tunnels need WebGL2 with 32-bit floating-point render targets. Without them a notice takes the place of each tunnel.&lt;/li&gt;&lt;li&gt;The history, the timeline &lt;strong&gt;A street with many names&lt;/strong&gt; (1878 to 1996) and the examples come with a twelve-item source list at the foot of the page, from Strouhal&amp;#39;s 1878 paper on aeolian tones, Reynolds 1883, Bénard 1908 and von Kármán 1911, through Roshko&amp;#39;s 1954 report, Williamson&amp;#39;s 1996 review and Billah and Scanlan&amp;#39;s 1991 paper on the Tacoma Narrows, to Latt and Chopard&amp;#39;s regularized collision, Wesfreid&amp;#39;s history of the Bénard–Kármán naming dispute and the NASA Earth Observatory page for the MISR image of Guadalupe Island from 11 June 2000.&lt;/li&gt;&lt;li&gt;This copy fixes four things in the original. Without WebGL2 the page stopped before the story script ran; it now carries on, with a notice in each tunnel. Each frame reset the frame clock after its own work, so the adaptive step budget never saw a slow frame; it now does. On a phone, a vertical swipe that started on the title tunnel dropped a disc of obstacle before the page scrolled; a touch there now paints only once it moves sideways, or on a tap. And two fractions in the equilibrium formula were broken entities.&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <title>Klangfiguren</title>
    <link href="https://dogum.github.io/artifact-shelf/a/klangfiguren/"/>
    <id>https://dogum.github.io/artifact-shelf/a/klangfiguren/</id>
    <published>2026-10-09T12:00:00Z</published>
    <updated>2026-10-09T12:00:00Z</updated>
    <category term="Simulations"/>
    <summary>Chladni figures from the real plate equation: a steel plate solved in the browser and driven at a chosen note, with up to 131,072 grains of sand on it.</summary>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://dogum.github.io/artifact-shelf/media/klangfiguren/poster.webp&quot; alt=&quot;&quot; width=&quot;640&quot;/&gt;&lt;/p&gt;&lt;p&gt;Chladni figures from the real plate equation: a steel plate solved in the browser and driven at a chosen note, with up to 131,072 grains of sand on it.&lt;/p&gt;&lt;p&gt;A long scrolling explainer on Chladni figures, the lines that sand draws on a vibrating plate. The page solves the equation of a thin elastic plate in the browser, drives the plate at a chosen frequency from a post at its centre, and pours up to 131,072 grains of sand on the answer, so every pattern is a computed vibration mode. The title is Chladni&amp;#39;s own word for them: sound figures. It runs from Hooke&amp;#39;s flour-dusted glass in 1680 through Chladni, Sophie Germain and Ritz to the luthiers who tune guitar and violin plates by the same figures.&lt;/p&gt;
&lt;h2 id=&quot;how-to-use-it&quot;&gt;How to use it&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;The title plate&lt;/strong&gt; steps through notes on its own, with the frequency, the mode number and the peak Γ under it. &lt;strong&gt;Sound off&lt;/strong&gt; toggles a tone that swells at each resonance, and &lt;strong&gt;Pour again&lt;/strong&gt; scatters fresh sand.&lt;/li&gt;&lt;li&gt;The contents bar jumps to &lt;strong&gt;01 A plate that sings&lt;/strong&gt; through &lt;strong&gt;09 Your plate&lt;/strong&gt;, and &lt;strong&gt;Notes&lt;/strong&gt;.&lt;/li&gt;&lt;li&gt;From 01 onward a plate stays pinned beside the text. Its toolbar switches the &lt;strong&gt;View&lt;/strong&gt; between &lt;strong&gt;Sand&lt;/strong&gt;, &lt;strong&gt;Motion&lt;/strong&gt; (the plate bending in 3D, exaggerated and slowed) and &lt;strong&gt;Γ&lt;/strong&gt; (a heat map of how hard the plate throws sand), sets what a &lt;strong&gt;Touch&lt;/strong&gt; does (&lt;strong&gt;Move drive&lt;/strong&gt;, &lt;strong&gt;Pour&lt;/strong&gt; or &lt;strong&gt;Wipe&lt;/strong&gt;), and has the sound toggle and &lt;strong&gt;Pour&lt;/strong&gt;.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;03 Ritz&amp;#39;s zoo&lt;/strong&gt; shows the first 24 modes as thumbnails. Tap one to drive it; the dim ones have a nodal line through the post, so the drive moves to where it can excite them.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;04 Only the right notes&lt;/strong&gt; sweeps the frequency and draws the resonance curve under the plate. &lt;strong&gt;Drag along the curve&lt;/strong&gt; to play the plate yourself; gold ticks mark modes the post can drive.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;05 One g&lt;/strong&gt; shows Γ with its Γ = 1 contour and a &lt;strong&gt;Drive force&lt;/strong&gt; slider: louder notes draw thinner lines. &lt;strong&gt;06 Faraday&amp;#39;s dust&lt;/strong&gt; adds yellow lycopodium, which heaps up where the plate moves most, and &lt;strong&gt;Pump out the air&lt;/strong&gt; sends it to the still lines like the sand.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;07 Round plates&lt;/strong&gt; switches between &lt;strong&gt;Drive at centre&lt;/strong&gt; (rings) and &lt;strong&gt;Drive near the rim&lt;/strong&gt; (petals) and plots the frequencies against Chladni&amp;#39;s count of lines. &lt;strong&gt;08 The luthier&amp;#39;s plate&lt;/strong&gt; cycles through the modes of an unbraced spruce guitar top with &lt;strong&gt;Next mode&lt;/strong&gt;.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;09 Your plate&lt;/strong&gt; opens everything: &lt;strong&gt;Square&lt;/strong&gt;, &lt;strong&gt;Rectangle&lt;/strong&gt; (with &lt;strong&gt;Aspect&lt;/strong&gt;), &lt;strong&gt;Circle&lt;/strong&gt; or &lt;strong&gt;Guitar top&lt;/strong&gt;; &lt;strong&gt;Steel&lt;/strong&gt;, &lt;strong&gt;Brass&lt;/strong&gt;, &lt;strong&gt;Aluminium&lt;/strong&gt;, &lt;strong&gt;Glass&lt;/strong&gt; or &lt;strong&gt;Spruce&lt;/strong&gt;; &lt;strong&gt;Thickness&lt;/strong&gt;, &lt;strong&gt;Size&lt;/strong&gt;, &lt;strong&gt;Frequency&lt;/strong&gt; with &lt;strong&gt;◀ ▶&lt;/strong&gt; to jump between resonances and &lt;strong&gt;Sweep&lt;/strong&gt;, &lt;strong&gt;Drive force&lt;/strong&gt;, &lt;strong&gt;Quality factor Q&lt;/strong&gt;; &lt;strong&gt;Sand&lt;/strong&gt;, &lt;strong&gt;Lycopodium&lt;/strong&gt; or &lt;strong&gt;Both&lt;/strong&gt;, &lt;strong&gt;Vacuum&lt;/strong&gt;, &lt;strong&gt;Pour&lt;/strong&gt; and &lt;strong&gt;Clear&lt;/strong&gt;. Readouts give the nearest mode, peak Γ, bending wavelength and wave speed, the largest amplitude and the number of modes below 4 kHz.&lt;/li&gt;&lt;/ul&gt;
&lt;h2 id=&quot;how-it-works&quot;&gt;How it works&lt;/h2&gt;
&lt;p&gt;The plate obeys Kirchhoff&amp;#39;s thin-plate equation with every edge free. For the square and the rectangle, the deflection is written as a double sum of normalised Legendre polynomials, 576 in all (24 each way on the square, shared out by how many half-waves fit each way on other plates), and the Rayleigh–Ritz method turns the equation into a 576 × 576 eigenproblem. The basis is orthonormal, so the mass matrix is the identity, and the four symmetry classes split it into four problems of 144, solved in the browser with Householder reduction and the QL algorithm. Spruce enters as four separate stiffnesses (Dx, Dy, D12, D66). The circle is solved exactly with Bessel functions, w = [Jₙ(kr) + C·Iₙ(kr)] cos nθ, with the frequencies found as roots of the 2 × 2 free-edge determinant. The guitar top uses the same polynomial basis (18 × 26) over its outline with the soundhole removed, solved offline; only its coefficients ship with the page. Modes are solved once per shape, material and aspect, since thickness and size only rescale the frequencies as h/L².&lt;/p&gt;
&lt;p&gt;The drive is a point force at the post. The forced response is a sum over all modes below 4 kHz, each with damping set by Q, and the post holds the plate&amp;#39;s rigid-body motion out of the picture. The story plate is 24 cm of steel, 0.8 mm thick, with 111 modes below 4 kHz.&lt;/p&gt;
&lt;p&gt;The sand is a reduced model, labelled as such on the page. Grains live in float textures on the GPU (131,072 on a desktop, 65,536 on phones). Where Γ = Ω²|w|/g exceeds 1, a grain is thrown up under real gravity with a take-off speed that grows with Γ − 1, lands a few millimetres away in a random direction with a slight lean down the amplitude slope, and rolls out a little. Below Γ = 1 it creeps slowly downhill in amplitude, which gives the crisp single lines. Grains that land off the plate fall off. Lycopodium drifts with the air currents in proportion to ∇Γ², and in vacuum it hops like sand. The sound is a sine at the drive frequency whose loudness follows how hard the plate is moving.&lt;/p&gt;
&lt;h2 id=&quot;notes&quot;&gt;Notes&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;The Checks table in the notes is computed when the page loads. The free square plate&amp;#39;s first frequencies (ν = 0.3) match Leissa&amp;#39;s 1969 values to every digit shown. The Ritz solution converges to a few parts in a million at mode 60. The circle&amp;#39;s Bessel roots match an independent solution, and the half-power width of a resonance equals f/Q.&lt;/li&gt;&lt;li&gt;Grain collisions, the weight of the sand, air loading and large-amplitude effects are left out, as the page states. The guitar frequencies are converged to a few per cent, the square&amp;#39;s to better than one part in a million.&lt;/li&gt;&lt;li&gt;The page needs WebGL2 with floating-point render targets. Without them a notice takes the place of each plate.&lt;/li&gt;&lt;li&gt;The timeline &lt;strong&gt;Three centuries of figures&lt;/strong&gt; and the eleven-item source list run from Chladni&amp;#39;s &lt;em&gt;Entdeckungen über die Theorie des Klanges&lt;/em&gt; (1787), Germain, Faraday and Kirchhoff, through Ritz (1909) and Leissa&amp;#39;s &lt;em&gt;Vibration of Plates&lt;/em&gt;, to Hutchins on violin plates and a 2016 paper on steering objects across a Chladni plate.&lt;/li&gt;&lt;li&gt;This copy fixes two things in the original. Each frame reset the frame clock after its own work, so the sand moved slower than real time; it now keeps time. And a leftover build note is gone from the footer.&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <title>Letters from the Sky</title>
    <link href="https://dogum.github.io/artifact-shelf/a/letters-from-the-sky/"/>
    <id>https://dogum.github.io/artifact-shelf/a/letters-from-the-sky/</id>
    <published>2026-10-09T12:00:00Z</published>
    <updated>2026-10-09T12:00:00Z</updated>
    <category term="Simulations"/>
    <summary>Snow crystals grown on the GPU from a published lattice model, steered through the temperatures and humidities of Nakaya&#39;s snow crystal diagram.</summary>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://dogum.github.io/artifact-shelf/media/letters-from-the-sky/poster.webp&quot; alt=&quot;&quot; width=&quot;640&quot;/&gt;&lt;/p&gt;&lt;p&gt;Snow crystals grown on the GPU from a published lattice model, steered through the temperatures and humidities of Nakaya&amp;#39;s snow crystal diagram.&lt;/p&gt;&lt;p&gt;A long scrolling explainer on snow crystals and why they look the way they do. A crystal grows on the GPU from Gravner and Griffeath&amp;#39;s published lattice model, one water-vapour step at a time, and the air it grows in is set by the temperature and humidity of Nakaya&amp;#39;s diagram. Its shape then records the conditions it met on the way down. The title is from Ukichiro Nakaya: &amp;quot;Snowflakes are letters sent from heaven.&amp;quot;&lt;/p&gt;
&lt;h2 id=&quot;how-to-use-it&quot;&gt;How to use it&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;The title crystal&lt;/strong&gt; grows on its own over drifting flakes, with its form, the air it grew in and a scale bar under it. &lt;strong&gt;Grow another&lt;/strong&gt; starts a new one.&lt;/li&gt;&lt;li&gt;The contents bar jumps to &lt;strong&gt;01 Why six&lt;/strong&gt; through &lt;strong&gt;08 Your cloud&lt;/strong&gt;, and &lt;strong&gt;Notes&lt;/strong&gt;.&lt;/li&gt;&lt;li&gt;From 01 onward a crystal stays pinned beside the text. Its &lt;strong&gt;View&lt;/strong&gt; switches between &lt;strong&gt;Photo&lt;/strong&gt; (lit like a micrograph), &lt;strong&gt;Bentley&lt;/strong&gt; (white on black), &lt;strong&gt;Record&lt;/strong&gt; (each part coloured by the air it froze in), &lt;strong&gt;Vapour&lt;/strong&gt; (the depleted air around it) and &lt;strong&gt;3D&lt;/strong&gt; (a turning ice plate, or a column when there is one), with &lt;strong&gt;Grow again&lt;/strong&gt; and &lt;strong&gt;Pause&lt;/strong&gt;.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;01 Why six&lt;/strong&gt; grows a single hexagonal plate from one cell of ice and shows the ice lattice. &lt;strong&gt;03 Why it branches&lt;/strong&gt; reads the vapour at the tips live. &lt;strong&gt;04 Why it has flat faces&lt;/strong&gt; has an &lt;strong&gt;Excess vapour at −15 °C&lt;/strong&gt; slider that changes the growth while it happens, so each change is written into the edge it reaches.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;05 Nakaya&amp;#39;s diagram&lt;/strong&gt; grows a crystal wherever you tap the full diagram. In the column bands, the crystal grows along its axis; switch to &lt;strong&gt;3D&lt;/strong&gt; to see it from the side.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;06 Letters from the sky&lt;/strong&gt; plays four journeys in the Record view: &lt;strong&gt;Plates on the tips&lt;/strong&gt;, &lt;strong&gt;Capped column&lt;/strong&gt;, &lt;strong&gt;Bands&lt;/strong&gt; and &lt;strong&gt;A long fall&lt;/strong&gt;. &lt;strong&gt;07 Twins and strangers&lt;/strong&gt; has a &lt;strong&gt;Turbulence&lt;/strong&gt; toggle and a live readout of the largest difference between arms.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;08 Your cloud&lt;/strong&gt; opens everything. &lt;strong&gt;Tap sets the air&lt;/strong&gt; lets you tap or drag the cloud chart at any moment; &lt;strong&gt;Draw a journey&lt;/strong&gt; lets you draw a path, then &lt;strong&gt;Fall along the path&lt;/strong&gt; or &lt;strong&gt;Clear path&lt;/strong&gt;. There are sliders for &lt;strong&gt;Temperature&lt;/strong&gt;, &lt;strong&gt;Excess vapour&lt;/strong&gt;, &lt;strong&gt;Growth speed&lt;/strong&gt; and &lt;strong&gt;Turbulence&lt;/strong&gt;, a table of the six published &lt;strong&gt;Model parameters&lt;/strong&gt;, and readouts of the form, diameter, supersaturation over ice, water saturation, model steps and column length.&lt;/li&gt;&lt;/ul&gt;
&lt;h2 id=&quot;how-it-works&quot;&gt;How it works&lt;/h2&gt;
&lt;p&gt;The growth model is Gravner and Griffeath&amp;#39;s (2008). Each cell of a hexagonal lattice holds an attachment flag, the mass of a thin quasi-liquid boundary layer, ice mass and vapour. Each step runs diffusion (reflecting at the crystal), freezing, attachment and melting. Whether an edge cell joins the crystal depends on how many ice neighbours it has: tips and flat faces need more mass than nooks, which is how the model tells facets from branches. Noise can be added to the vapour for turbulence. On the GPU the state lives in 32-bit float textures in axial coordinates, 512 cells across on a computer and 384 on a phone, inside a hexagonal domain whose rim is held at the cloud&amp;#39;s vapour density. One step is three shader passes, plus a growth record of the time, temperature, humidity and kind of growth for every cell as it freezes. Neighbour sums are added in an order that does not depend on direction, so the six arms stay identical to the last bit unless turbulence is on.&lt;/p&gt;
&lt;p&gt;The model itself knows nothing about temperature, so the page maps the diagram onto it. Vapour pressures over ice and supercooled water come from Murphy and Koop (2005), and the chart&amp;#39;s vertical axis is the excess vapour density over ice saturation, with the water-saturation line drawn in. In the plate bands (−1 to −3.5 °C and −10 to −22 °C), the humidity picks one of six published parameter sets, from hexagonal plate through ribbed, sectored and stellar plates to stellar dendrites and fernlike crystals. Near −2 °C only plates grow. In the column bands, the lattice runs at half the vapour and a column length grows at a rate that peaks near −5 °C. The 3D view draws it as a hexagonal prism with the lattice crystal at each end, so capped columns form naturally. The number of steps per frame adapts toward about 14 seconds per crystal.&lt;/p&gt;
&lt;p&gt;The Photo view averages the field once over each hexagon and lights the edges and ridges with a warm lamp from low left and a cool one from high right over a blue backlight. The 3D view draws a thin double-sided ice sheet with Fresnel reflection, refraction and glints.&lt;/p&gt;
&lt;h2 id=&quot;notes&quot;&gt;Notes&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;The notes include live checks. Murphy–Koop vapour pressures at −15 °C agree with Goff–Gratch to within a few tenths of a pascal. The supersaturation of water-saturated air at −15 °C comes out at about 16%. And the arms are compared live while a crystal grows without turbulence.&lt;/li&gt;&lt;li&gt;The habit mapping follows the observed diagram, and the columns are drawn rather than grown in 3D, as the page states.&lt;/li&gt;&lt;li&gt;The crystals need WebGL2 with floating-point render targets. Without them a notice takes the place of each crystal.&lt;/li&gt;&lt;li&gt;The history runs from Kepler&amp;#39;s &lt;em&gt;On the Six-Cornered Snowflake&lt;/em&gt; (1611) and Bentley&amp;#39;s first photomicrograph of a snow crystal (1885) to Nakaya&amp;#39;s laboratory crystals of 1936 and Kobayashi&amp;#39;s extension of the diagram (1961).&lt;/li&gt;&lt;li&gt;This copy fixes the frame clock in the original. Each frame reset the clock after its own work, so the step budget never saw a slow frame and pacing on slow GPUs was off; the clock now resets only when a loop starts from idle.&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <title>Lamplight Shadow Theater</title>
    <link href="https://dogum.github.io/artifact-shelf/a/lamplight-shadow-theater/"/>
    <id>https://dogum.github.io/artifact-shelf/a/lamplight-shadow-theater/</id>
    <published>2026-10-08T12:00:00Z</published>
    <updated>2026-10-08T12:00:00Z</updated>
    <category term="Toys"/>
    <summary>Make a hand shadow in front of your webcam, hold it still, and it peels off the paper screen as a fox, rabbit, dog, swan or bird with a name and a mood.</summary>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://dogum.github.io/artifact-shelf/media/lamplight-shadow-theater/poster.webp&quot; alt=&quot;&quot; width=&quot;640&quot;/&gt;&lt;/p&gt;&lt;p&gt;Make a hand shadow in front of your webcam, hold it still, and it peels off the paper screen as a fox, rabbit, dog, swan or bird with a name and a mood.&lt;/p&gt;&lt;p&gt;A paper shadow-puppet screen lit by a lamp behind it. Your hands, seen through the webcam, cast soft shadows on the paper. Hold one of five classic hand shapes still, a ring of light gathers around it, and the shadow steps off your hand onto the stage as a living cut-paper animal. Each one gets a name and a temperament, wanders the bank and the pond, and reacts to your hands and to the others. Without a camera, the mouse plays the hand.&lt;/p&gt;
&lt;h2 id=&quot;how-to-use-it&quot;&gt;How to use it&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;Press &lt;strong&gt;Light the lamp&lt;/strong&gt; and allow the camera, or choose &lt;strong&gt;No camera? Play with the mouse&lt;/strong&gt;.&lt;/li&gt;&lt;li&gt;Make a shape from the &lt;strong&gt;Hand Shapes&lt;/strong&gt; card and hold it still until the light closes in:&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Rabbit&lt;/strong&gt;: two fingers up for ears, thumb holding the rest down.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Fox&lt;/strong&gt;: thumb touching the middle fingers, pointer and pinky as ears.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Dog&lt;/strong&gt;: hand on its side, thumb up for an ear. Drop your pinky to bark.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Swan&lt;/strong&gt;: fingertips together for a beak, your arm as the neck.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Bird&lt;/strong&gt;: two hands hooked at the thumbs with the fingers spread. Two people can share it.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;In mouse mode, click a shape on the card, then hold the mouse still on the stage. Press and hold to pinch. &lt;strong&gt;Escape&lt;/strong&gt; relaxes the hand.&lt;/li&gt;&lt;li&gt;Then play with them. &lt;strong&gt;Poke&lt;/strong&gt; gently to say hello. &lt;strong&gt;Pinch&lt;/strong&gt; thumb and pointer to hold a crumb, then let go to drop it. A quick &lt;strong&gt;swoosh&lt;/strong&gt; frightens the shy ones. Hold very &lt;strong&gt;still&lt;/strong&gt; and a bird may land on you.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Sound&lt;/strong&gt; toggles the synthesized sounds, &lt;strong&gt;Peek at camera&lt;/strong&gt; shows the mirrored webcam feed in a corner, and &lt;strong&gt;Curtain call&lt;/strong&gt; brings the cast out to bow. &lt;strong&gt;Tonight&amp;#39;s Cast&lt;/strong&gt; lists everyone on stage with their name and mood.&lt;/li&gt;&lt;/ul&gt;
&lt;h2 id=&quot;how-it-works&quot;&gt;How it works&lt;/h2&gt;
&lt;p&gt;Hand tracking uses MediaPipe&amp;#39;s Hand Landmarker, loaded from a public CDN and run inside the tab, so no video leaves the computer. It reports 21 landmarks per hand. The recognizer reads joint angles and finger ratios from the 3D world landmarks so the result does not depend on how the hand is turned, and uses the 2D image points only for orientation checks such as the dog&amp;#39;s sideways pose. Tracks are matched frame to frame by wrist distance and smoothed. A shape has to be held still for a moment before it counts, and it must be released before it can make another creature.&lt;/p&gt;
&lt;p&gt;The screen is drawn in layers. A procedural washi-paper texture (mottled pulp, long fibers, one glued seam) is lit by a warm falloff from the lamp. Hands and creatures are drawn as solid silhouettes into a shadow mask, blurred by how far they sit from the paper, and multiplied over the lit sheet. A newborn creature starts soft and close to the hand and sharpens as it lands on the stage. Eye holes and collars are cut out so light shows through, the way it does with real paper puppets.&lt;/p&gt;
&lt;p&gt;Each animal is a set of keyframed poses blended by weight, with a trotting or hopping gait, breathing, blinking and tail motion layered on top. Behaviour is a small state machine (idle, walk, sniff, beg, eat, perch, flee, sleep, swim) steered by a temperament drawn at birth: bravery, energy, curiosity, friendliness and appetite. Two creatures can meet and chase, play, or wait for a shy one to warm up. All sounds are synthesized with the Web Audio API; there are no audio files.&lt;/p&gt;
&lt;p&gt;A small kinematic hand model produces the same 21 landmarks MediaPipe would. It draws the illustrations on the Hand Shapes card, drives the mouse hand, and lets the recognizer be tested without a camera.&lt;/p&gt;
&lt;h2 id=&quot;notes&quot;&gt;Notes&lt;/h2&gt;
&lt;p&gt;The hand-tracking model downloads once from &lt;code&gt;cdn.jsdelivr.net&lt;/code&gt; and &lt;code&gt;storage.googleapis.com&lt;/code&gt;. Camera access needs a secure page (https or localhost), which the shelf provides.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Recipe Diagram</title>
    <link href="https://dogum.github.io/artifact-shelf/a/recipe-diagram/"/>
    <id>https://dogum.github.io/artifact-shelf/a/recipe-diagram/</id>
    <published>2026-10-08T12:00:00Z</published>
    <updated>2026-10-08T12:00:00Z</updated>
    <category term="Tools"/>
    <summary>Write a recipe as indented plain text and get a flow-table diagram, a written method, pan-size scaling and a step-by-step cook mode with timers.</summary>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://dogum.github.io/artifact-shelf/media/recipe-diagram/poster.webp&quot; alt=&quot;&quot; width=&quot;640&quot;/&gt;&lt;/p&gt;&lt;p&gt;Write a recipe as indented plain text and get a flow-table diagram, a written method, pan-size scaling and a step-by-step cook mode with timers.&lt;/p&gt;&lt;p&gt;A recipe tool that draws each dish as a table. Every ingredient is a row on the left, every operation is a merged cell spanning the ingredients it takes in, and the cells funnel rightward into the finished dish. The table is computed from an indented plain-text recipe, so changing the pan, the batch size or the units redraws the amounts, the written method and the cooking steps together.&lt;/p&gt;
&lt;h2 id=&quot;how-to-use-it&quot;&gt;How to use it&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;Pick a recipe from &lt;strong&gt;Recipe&lt;/strong&gt;. Five come built in: Espresso Brownies, Buttermilk Pancakes, Everyday Vinaigrette, Skillet Cornbread and Overnight Focaccia. &lt;strong&gt;+&lt;/strong&gt; starts a new one.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Diagram&lt;/strong&gt;, &lt;strong&gt;Recipe&lt;/strong&gt; and &lt;strong&gt;Edit&lt;/strong&gt; switch between the table, the written-out recipe and the source text. Hover a box, or press Tab to enter the table and move with the arrow keys, to highlight everything that flows into it.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Pan&lt;/strong&gt; scales by pan area when the recipe names a pan size. Without one the control reads &lt;strong&gt;Batch&lt;/strong&gt; and goes from half to triple. &lt;strong&gt;Units&lt;/strong&gt; shows US, metric or both.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Cook this&lt;/strong&gt; steps through the method one operation at a time, lighting the current box and listing its ingredients as tick boxes. A step with a time in it offers a timer. Keys: ← and → to move, space for next, t to start the timer, esc to leave. On a narrow screen it shows a step list in place of the table.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Paste a recipe&lt;/strong&gt; turns an ordinary ingredients-and-method recipe into the format and lists what it had to guess. &lt;strong&gt;Copy prompt for an LLM&lt;/strong&gt; copies instructions for getting the same result from any AI assistant; paste its answer back into the box and it is used as written.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Share&lt;/strong&gt;, &lt;strong&gt;Copy&lt;/strong&gt; (plain text), &lt;strong&gt;PNG&lt;/strong&gt; and &lt;strong&gt;Print&lt;/strong&gt; take it elsewhere. Recipes you write are saved in your browser.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;In &lt;strong&gt;Edit&lt;/strong&gt; the recipe is plain text. A line with lines indented under it is an operation, written &lt;code&gt;verb | detail&lt;/code&gt;. A line with nothing under it is an ingredient, written &lt;code&gt;US | metric | name | note&lt;/code&gt;, where the metric and the note are optional and an amount with no number (&lt;code&gt;pinch&lt;/code&gt;, &lt;code&gt;to taste&lt;/code&gt;) is left alone when scaling. Header lines sit at zero indent, and &lt;code&gt;{pan}&lt;/code&gt; and &lt;code&gt;{oven}&lt;/code&gt; anywhere in the text are filled in from them. &lt;code&gt;@dry&lt;/code&gt; after a verb names a branch, and a line starting &lt;code&gt;&amp;gt;&lt;/code&gt; sets aside part of an ingredient declared elsewhere for a later step. A trimmed version of the built-in cornbread:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;title: Skillet Cornbread
pan: 9-in round
oven: 425F | 220C
prep: Heat the skillet in the oven while it comes up to {oven}

bake | {oven}, 20 to 24 min, until the top springs back
  swirl in | to coat the hot skillet, then pour in the batter
    stir | until just combined
      whisk @dry
        1 1/4 cups | 175 g | fine cornmeal
        2 tsp | 9 g | baking powder
      whisk @wet
        1 1/4 cups | 300 mL | buttermilk
        6 Tbs | 85 g | unsalted butter | melted
    &amp;gt; 2 Tbs | 28 g | unsalted butter&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;how-it-works&quot;&gt;How it works&lt;/h2&gt;
&lt;p&gt;The parser reads the text line by line. Zero-indent lines with a known key become metadata and &lt;code&gt;#&lt;/code&gt; lines are comments. Everything else goes into a tree through an indentation stack: each new line pops the stack until the top is less indented than itself, then becomes that line&amp;#39;s child. Lines with children are operations; the rest are ingredients, with amounts parsed as whole numbers, decimals, fractions or mixed numbers, or kept as literal text. A second line at the outermost level is an error, because everything has to flow into one final step. Regular expressions pull durations (&lt;code&gt;30 to 40 min&lt;/code&gt;, &lt;code&gt;1 hr 30 min&lt;/code&gt;) and an &lt;code&gt;until…&lt;/code&gt; doneness cue out of each operation&amp;#39;s detail; anything over six hours, or marked &lt;code&gt;overnight&lt;/code&gt;, counts as a rest and gets no countdown.&lt;/p&gt;
&lt;p&gt;The diagram is an HTML table with merged cells. Each ingredient gets one row, in source order. Each operation&amp;#39;s column is its height above the ingredients (one more than its tallest child), its rowspan is the number of ingredient rows beneath it, and it is written into the row of its first ingredient. Every cell&amp;#39;s colspan runs from its own column to its parent&amp;#39;s, so an ingredient that goes straight into a late step stretches across the empty columns to reach it. Prep and finish lines become full-width banner rows above and below. On a narrow screen a CSS transform shrinks the table to fit, with an &lt;strong&gt;Actual size&lt;/strong&gt; button to scroll it at full size instead.&lt;/p&gt;
&lt;p&gt;Scaling multiplies both amount columns by one factor. When the &lt;code&gt;pan:&lt;/code&gt; line gives dimensions (&lt;code&gt;8x8 in&lt;/code&gt;, &lt;code&gt;9-in round&lt;/code&gt;, centimetres too), the app works out the area, offers a list of ten common rectangular, round and loaf pans, and scales by the ratio of areas, which keeps the batter the same depth. Batch scaling keeps the vessel, so at 1.5× or more a note warns that the batter sits deeper and will take longer, and for an oven recipe suggests dropping the temperature about 25°F (15°C). Both amount columns come from the recipe text, so nothing is converted between cups and grams; &lt;strong&gt;Units&lt;/strong&gt; chooses which to show. Scaled US volumes are re-expressed in whichever of teaspoons, tablespoons or cups lands on a measurable fraction (6 tsp becomes 2 Tbs, 12 Tbs becomes ¾ cup, 9 Tbs stays 9 Tbs) and printed as eighths, thirds or sixths. Metric amounts round more coarsely as they grow and roll over to kg and L at 1000. Counted items such as eggs that stop landing on a whole number get a † and a note to beat them and weigh out the metric amount.&lt;/p&gt;
&lt;p&gt;The written recipe comes from the same tree. A post-order walk, children before parents, puts each operation after the steps that feed it, and each becomes one sentence: the verb, then its ingredients as a list (&amp;quot;Whisk the buttermilk, eggs, and unsalted butter&amp;quot;). An operation that joins branches names them from their &lt;code&gt;@&lt;/code&gt; labels (&amp;quot;Stir the dry and wet mixtures together&amp;quot;) or counts them when they have none. Verbs ending in a preposition, like &lt;code&gt;fold in&lt;/code&gt; or &lt;code&gt;swirl in&lt;/code&gt;, take their ingredients directly, a &lt;code&gt;&amp;gt;&lt;/code&gt; ingredient becomes &amp;quot;the reserved unsalted butter&amp;quot;, and the detail joins with or without a comma depending on whether it reads on from the verb (&lt;code&gt;until…&lt;/code&gt;, &lt;code&gt;for…&lt;/code&gt;). Prep lines open the method and finish lines close it. Cook mode and the plain-text copy use the same sequence.&lt;/p&gt;
&lt;h2 id=&quot;notes&quot;&gt;Notes&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Paste a recipe&lt;/strong&gt; is rule-based. It splits the paste at Ingredients and Method headings, or works through the lines in order when there are none, reads each ingredient line into the four-column form (a parenthetical like &lt;code&gt;(125 g)&lt;/code&gt; becomes the metric amount), splits the method into sentences, sets aside preheat-style prep and serving-style finish sentences, and gives each ingredient to the first step that names it. Steps come out as one straight chain, so branches have to be indented by hand, and the dialog says so.&lt;/li&gt;&lt;li&gt;Timers run off wall-clock end times, so several can run at once and they survive leaving cook mode or reloading the page. They beep through Web Audio and vibrate where the device allows, and the screen is kept awake with the Wake Lock API while cooking or while a timer runs.&lt;/li&gt;&lt;li&gt;On an ordinary web address, &lt;strong&gt;Share&lt;/strong&gt; deflates the recipe text with CompressionStream into the link&amp;#39;s &lt;code&gt;#&lt;/code&gt; fragment; inside a frame or a saved file it hands over the recipe as plain text instead. &lt;strong&gt;PNG&lt;/strong&gt; runs html2canvas on a clean offscreen copy of the diagram, with an SVG &lt;code&gt;foreignObject&lt;/code&gt; render as the fallback.&lt;/li&gt;&lt;li&gt;On claude.ai the paste dialog also offers &lt;strong&gt;Convert with Claude&lt;/strong&gt;. Here that button is hidden and recipes are kept in the browser&amp;#39;s local storage.&lt;/li&gt;&lt;li&gt;This copy fixes the diagram for recipes that set aside part of an ingredient with a &lt;code&gt;&amp;gt;&lt;/code&gt; line. The reserved row used to leave an empty box to its right; it now runs across to the step that uses it, as in the Skillet Cornbread sample.&lt;/li&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <title>Catching Booster 12</title>
    <link href="https://dogum.github.io/artifact-shelf/a/catching-booster-12/"/>
    <id>https://dogum.github.io/artifact-shelf/a/catching-booster-12/</id>
    <published>2026-10-07T12:00:00Z</published>
    <updated>2026-10-07T12:00:00Z</updated>
    <category term="Explainers"/>
    <summary>The first tower catch of a Super Heavy booster, rebuilt from webcast telemetry as eight drawing sheets, ending in a catch sandbox you can fly.</summary>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://dogum.github.io/artifact-shelf/media/catching-booster-12/poster.webp&quot; alt=&quot;&quot; width=&quot;640&quot;/&gt;&lt;/p&gt;&lt;p&gt;The first tower catch of a Super Heavy booster, rebuilt from webcast telemetry as eight drawing sheets, ending in a catch sandbox you can fly.&lt;/p&gt;&lt;p&gt;Eight interactive engineering-drawing sheets about Starship Flight 5 on 13 October 2024, when Super Heavy Booster 12 came back from 96 km and was caught by the arms of its launch tower. The flight path is reconstructed from the altitude and speed readouts on the SpaceX webcast, and every number on the page is tagged HUD, SRC, CALC or EST, so you can see which figures were read off the video, which come from a published source, which were calculated and which are estimates.&lt;/p&gt;
&lt;h2 id=&quot;how-to-use-it&quot;&gt;How to use it&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;Scroll through the sheets: 01 Delete the legs, 02 Mechazilla, 03 Flight profile, 04 Go / no-go, 05 Boostback &amp;amp; entry, 06 The divert, 07 The grab, 08 Try the catch. The page ends with a &amp;quot;What to trust&amp;quot; table and the full source list.&lt;/li&gt;&lt;li&gt;Sheet 02: drag the slider to take the arms from open to closed to loaded.&lt;/li&gt;&lt;li&gt;Sheet 03: drag across the charts or press &lt;strong&gt;Play&lt;/strong&gt; at 1×, 5×, 15× or 40×. The event chips jump to liftoff, max-q, MECO, hot staging, boostback, apogee, the landing burn and the catch. With the chart focused, arrow keys step 1 s (Shift for 10 s) and Space plays.&lt;/li&gt;&lt;li&gt;Sheet 04: click the switches in the commit-logic diagram, or load &lt;strong&gt;Flight 5&lt;/strong&gt;, &lt;strong&gt;Flight 6&lt;/strong&gt; or &lt;strong&gt;Command too late&lt;/strong&gt;.&lt;/li&gt;&lt;li&gt;Sheet 08: choose &lt;strong&gt;Auto&lt;/strong&gt;, &lt;strong&gt;Throttle&lt;/strong&gt; or &lt;strong&gt;Manual&lt;/strong&gt;, set the faults (ignition timing, crosswind gusts, position error, booster mass error, propellant at ignition, arm close delay, engine failure) and press &lt;strong&gt;Light engines&lt;/strong&gt;. When you have the controls, W and S or the up and down arrows change throttle, A and D or left and right tilt the booster, and Space closes the arms. &lt;strong&gt;Run 300&lt;/strong&gt; scatters 300 autopilot attempts at the current settings.&lt;/li&gt;&lt;/ul&gt;
&lt;h2 id=&quot;how-it-works&quot;&gt;How it works&lt;/h2&gt;
&lt;p&gt;The speed trace is an OCR of the webcast HUD, taken frame by frame from an open-source telemetry extractor and stored in the page at 0.5 s intervals. The HUD shows altitude only in whole kilometres, so a smooth curve is fitted through the moments the digit changes. Horizontal speed is the square root of speed squared minus climb rate squared, integrated over time to get downrange distance; the reconstructed path closes on the tower within 0.12 km after an 88 km excursion, and that residual is removed as a linear drift.&lt;/p&gt;
&lt;p&gt;Mach number, dynamic pressure and g-loads are derived from the path with a standard atmosphere. The unpowered fall implies a ballistic coefficient near 2,500 kg/m². Propellant has no published figures, so it comes from running the rocket equation backwards from an assumed catch mass through the burns seen in the telemetry.&lt;/p&gt;
&lt;p&gt;The sandbox is a 2-D point-mass model stepped at 120 Hz, started from the reconstructed state at landing-burn ignition: 1.77 km up, 148 m/s west, 317 m/s down. It uses Raptor 2 sea-level thrust of 2.26 MN, an assumed 327 s specific impulse, a 40 percent throttle floor and drag from the measured ballistic coefficient. The autopilot follows the reconstructed descent for the 13-engine phase, then flies a re-planned constant-deceleration descent with throttle and tilt limits, steering sideways along a quintic reference curve to the rail centre. The Monte Carlo batch runs 300 seeded attempts with Gaussian jitter on ignition time and mass, and plots where each one met the rails and how fast.&lt;/p&gt;
&lt;p&gt;The drawings are hand-built SVG with dimension lines, part balloons and hidden lines, and the sandbox draws to a canvas. No libraries are loaded.&lt;/p&gt;
&lt;h2 id=&quot;notes&quot;&gt;Notes&lt;/h2&gt;
&lt;p&gt;A fan explainer, not affiliated with SpaceX. Catch tolerances in the sandbox (±1.5 m along the rail, under 2 m/s for a clean catch) are the author&amp;#39;s estimates, since SpaceX has not published them. The telemetry comes from the MIT-licensed StarshipTelemetryExtractor CSV for Flight 5; other sources include SpaceX&amp;#39;s mission page, NASASpaceflight, SpaceNews, Space.com, IMechE and Wikipedia, all linked at the bottom of the page.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Desk, by daylight</title>
    <link href="https://dogum.github.io/artifact-shelf/a/desk-by-daylight/"/>
    <id>https://dogum.github.io/artifact-shelf/a/desk-by-daylight/</id>
    <published>2026-10-07T12:00:00Z</published>
    <updated>2026-10-07T12:00:00Z</updated>
    <category term="Simulations"/>
    <summary>A desk seen from above, lit by the real sun and moon for any place and time, with a working sundial, window-pane shadows and a ray-marched WebGL scene.</summary>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://dogum.github.io/artifact-shelf/media/desk-by-daylight/poster.webp&quot; alt=&quot;&quot; width=&quot;640&quot;/&gt;&lt;/p&gt;&lt;p&gt;A desk seen from above, lit by the real sun and moon for any place and time, with a working sundial, window-pane shadows and a ray-marched WebGL scene.&lt;/p&gt;&lt;p&gt;A wooden desk seen from straight above, lit by the sun or the moon as they stand at this moment over a chosen place on Earth. The shadows of a mug, a succulent, a pencil and a glass ball swing round through the day, sunlight comes in through the panes of a window, and a brass sundial laid out for the desk&amp;#39;s latitude reads solar time beside a card that shows the clock. Every shadow is traced from the computed sun or moon direction, so the scene matches the sky outside.&lt;/p&gt;
&lt;h2 id=&quot;how-to-use-it&quot;&gt;How to use it&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;It opens &lt;strong&gt;Live&lt;/strong&gt;, following the real clock. Drag the &lt;strong&gt;Day&lt;/strong&gt; slider to move through today and the &lt;strong&gt;Year&lt;/strong&gt; slider to move through the year at the same clock time. &lt;strong&gt;Back to now&lt;/strong&gt; returns to the present.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;▶&lt;/strong&gt; plays the day (one day every 40 seconds). The figure-eight button holds the clock time and plays the year, about eight days a second.&lt;/li&gt;&lt;li&gt;Click the card, or press C, to turn it over. Its five sides cover the moment, the sundial against the clock, the light on the desk in lux, the planets that are up, and the year at this place.&lt;/li&gt;&lt;li&gt;The compass button at the right end of the strip opens &lt;strong&gt;Place, window and time&lt;/strong&gt;:&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Find a city&lt;/strong&gt;, type &lt;strong&gt;Latitude&lt;/strong&gt; and &lt;strong&gt;Longitude&lt;/strong&gt; and press &lt;strong&gt;Set position&lt;/strong&gt;, or press &lt;strong&gt;Use my location&lt;/strong&gt;. The quick trips (Tromsø, Reykjavík, Kashgar, Quito, Honolulu, Singapore, Sydney, Ushuaia) are places where the light behaves differently, each with a note. &lt;strong&gt;Back home&lt;/strong&gt; returns to your own position. &lt;strong&gt;Clock&lt;/strong&gt; overrides the time zone.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Which way the screen faces&lt;/strong&gt;: drag the compass rose or the slider, or use the &lt;strong&gt;N&lt;/strong&gt;, &lt;strong&gt;E&lt;/strong&gt;, &lt;strong&gt;S&lt;/strong&gt; and &lt;strong&gt;W&lt;/strong&gt; buttons. On a phone, &lt;strong&gt;Follow this phone&amp;#39;s compass&lt;/strong&gt; reads the device&amp;#39;s orientation.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;The window&lt;/strong&gt;: put it &lt;strong&gt;Ahead&lt;/strong&gt;, &lt;strong&gt;Left&lt;/strong&gt;, &lt;strong&gt;Right&lt;/strong&gt; or &lt;strong&gt;Behind&lt;/strong&gt;, or choose &lt;strong&gt;Open sky&lt;/strong&gt; to take the walls away.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Jump ahead to&lt;/strong&gt; the next &lt;strong&gt;Equinox&lt;/strong&gt;, &lt;strong&gt;Solstice&lt;/strong&gt;, &lt;strong&gt;Full moon&lt;/strong&gt; or &lt;strong&gt;New moon&lt;/strong&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Keys: ← and → move ten minutes (with Shift, an hour), ↑ and ↓ move a day (with Shift, a week), Space plays the day, Y plays the year, C turns the card, N returns to now.&lt;/li&gt;&lt;/ul&gt;
&lt;h2 id=&quot;how-it-works&quot;&gt;How it works&lt;/h2&gt;
&lt;p&gt;The sun&amp;#39;s position comes from the low-precision NOAA and Meeus formulas: mean longitude and anomaly, the equation of centre, a correction for nutation and aberration, and the obliquity of the ecliptic, turned into altitude and azimuth through Greenwich mean sidereal time and the local hour angle, with Bennett&amp;#39;s formula for refraction. The moon uses a truncated form of the series in chapter 47 of Meeus, corrected for parallax, and the card draws its phase with the bright limb tilted by the parallactic angle, as it would look in your sky. Sunrise, sunset, civil twilight and golden hour are found by sampling the sun&amp;#39;s elevation every ten minutes and bisecting the crossings of −0.833°, −6° and +6°. Solar noon comes from Newton steps on the hour angle. The planets side solves Kepler&amp;#39;s equation from JPL&amp;#39;s approximate orbital elements for Mercury through Saturn.&lt;/p&gt;
&lt;p&gt;Light is modelled in lux. Direct sunlight is dimmed per colour channel by Beer–Lambert extinction through Rayleigh, aerosol and ozone optical depths, with the Kasten–Young air mass formula, which is what turns a low sun orange. Skylight follows a table of illuminance against solar elevation down through astronomical twilight, and moonlight scales with phase by the Krisciunas–Schaefer law. An automatic exposure maps the total onto the screen through an ACES filmic curve, and in dim light the colour drains toward blue-grey, as it does when the eye switches from cones to rods. The paper strip of controls is tinted by a CPU copy of the same lighting, and its CSS shadow moves with the sun as if it floated 1.4 cm above the desk.&lt;/p&gt;
&lt;p&gt;The scene is one WebGL fragment shader that ray-marches signed distance fields for the card, the dial, the mug of coffee, the potted succulent, a hexagonal pencil and a sheet of graph paper with a pin. Shadows use the SDF soft-shadow method, with the penumbra set by the sun&amp;#39;s angular size. Surfaces get GGX specular highlights with Schlick Fresnel, SDF ambient occlusion and fBm wood grain. The glass ball is traced analytically: it refracts the desk behind it and focuses a caustic at the ball-lens focal distance nR/2(n−1), slightly different for red, green and blue. The window is a wall plane with a grid of small panes; light reaches the desk only through the glass, and the bar shadows blur with distance from it. While you drag, a low-resolution pass draws; the full image then fills in a strip at a time.&lt;/p&gt;
&lt;p&gt;The sundial is a horizontal dial. Its quarter-hour lines, from 4 am to 8 pm solar time, follow tan θ = sin φ · tan H, the gnomon&amp;#39;s edge rises at the latitude angle, and the plate turns to true north whichever way the screen faces. On the graph paper the pinhead works as a nodus: dots mark where its shadow falls at each whole hour today, a line traces the whole day, and a figure eight (the analemma) shows where it falls at one clock hour on every third day of the year. All calendar arithmetic runs in the time zone of the place on the desk, through &lt;code&gt;Intl.DateTimeFormat&lt;/code&gt;, so the card can explain the gap between dial and clock in parts: daylight saving, the place&amp;#39;s distance from its zone&amp;#39;s central meridian, and the equation of time.&lt;/p&gt;
&lt;h2 id=&quot;notes&quot;&gt;Notes&lt;/h2&gt;
&lt;p&gt;Until you set a position, the desk uses a fixed default one and your device&amp;#39;s time zone. &lt;strong&gt;Use my location&lt;/strong&gt; rounds the position to about a kilometre; if the browser blocks location, the button hides itself, and &lt;strong&gt;Find a city&lt;/strong&gt; or typed coordinates work instead. Your position, screen direction and window choice are kept in this browser. The Year slider&amp;#39;s track is a small daylight map, one column per day and one row per half hour of clock time, so the switch to and from daylight saving shows as a step. The motto on the dial, SINE SOLE SILEO, means &amp;quot;without the sun I am silent&amp;quot;.&lt;/p&gt;
&lt;p&gt;This copy differs from the original in two ways: its default position is one of the cities from its own list, and it reads your location only after you press &lt;strong&gt;Use my location&lt;/strong&gt; (or on load, if you have already allowed it for this site).&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Merrow Pocket Plan</title>
    <link href="https://dogum.github.io/artifact-shelf/a/merrow-pocket-plan/"/>
    <id>https://dogum.github.io/artifact-shelf/a/merrow-pocket-plan/</id>
    <published>2026-10-05T12:00:00Z</published>
    <updated>2026-10-05T12:00:00Z</updated>
    <category term="Games"/>
    <summary>A pocket street map of an invented city, scored into 32 panels you fold like real paper in 3D. Somewhere in its folds is a walk the city forgot.</summary>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://dogum.github.io/artifact-shelf/media/merrow-pocket-plan/poster.webp&quot; alt=&quot;&quot; width=&quot;640&quot;/&gt;&lt;/p&gt;&lt;p&gt;A pocket street map of an invented city, scored into 32 panels you fold like real paper in 3D. Somewhere in its folds is a walk the city forgot.&lt;/p&gt;&lt;p&gt;A folding street plan of Merrow, an invented river city, printed as a 1958 pocket map and lying on a wooden desk in 3D. The sheet is scored into 32 panels and behaves like paper: valley and mountain folds, flaps that carry whatever lies on them, and creases that stay in after you open it out. Somewhere in its folds is a walk the city forgot, and it only joins up when the sheet is folded the right way.&lt;/p&gt;
&lt;h2 id=&quot;how-to-use-it&quot;&gt;How to use it&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;The map starts folded as bought, cover up. Press &lt;strong&gt;Open the map&lt;/strong&gt; to let it fall open, or drag the cover downward to open it panel by panel yourself.&lt;/li&gt;&lt;li&gt;To fold, press on a panel and drag it across one of the scored creases. Let go past halfway and it folds. A dashed guide shows the crease; if the paper can&amp;#39;t fold that way, the flap wobbles and the reason appears (&amp;quot;no crease there&amp;quot;, &amp;quot;the whole sheet would move&amp;quot;).&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Valley&lt;/strong&gt; (V) brings the flap over toward you and &lt;strong&gt;Mountain&lt;/strong&gt; (M) sends it behind. Hold Shift while dragging to swap. A valley fold carries everything lying on the flap; a mountain fold carries everything under it.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Turn over&lt;/strong&gt; (T) shows the reverse: cover, street index, places of interest, notes on the city and its old walks. &lt;strong&gt;Turn around&lt;/strong&gt; (R) spins the sheet half a turn on the desk.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Undo&lt;/strong&gt; (Z) takes back the last fold, &lt;strong&gt;Unfold&lt;/strong&gt; flattens everything, and &lt;strong&gt;Fit&lt;/strong&gt; (F) frames the sheet in the window.&lt;/li&gt;&lt;li&gt;Scroll or pinch to zoom, drag the desk to slide the map, and right-drag (or Alt-drag) to tilt and look along the folds.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Lamp&lt;/strong&gt; sets the light&amp;#39;s direction and height, with presets for &lt;strong&gt;Raking light&lt;/strong&gt;, &lt;strong&gt;Overhead&lt;/strong&gt; and &lt;strong&gt;Desk lamp&lt;/strong&gt;. A low lamp makes the creases easy to read.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Cartographer&amp;#39;s key&lt;/strong&gt; holds four hints that open one at a time, then the answer with a &lt;strong&gt;Fold it for me&lt;/strong&gt; button. &lt;strong&gt;Sound&lt;/strong&gt; turns the paper noises on and off.&lt;/li&gt;&lt;/ul&gt;
&lt;h2 id=&quot;how-it-works&quot;&gt;How it works&lt;/h2&gt;
&lt;p&gt;The fold engine treats the sheet as an 8 × 4 grid. Since every fold runs along a scored line, each panel&amp;#39;s position is an axis-aligned reflection plus offset (a flip in x, a flip in y, and a translation in whole cells), and the whole stack is one bottom-to-top ordering of panel ids. A fold reflects the moving panels across the crease and puts them on top (valley) or underneath (mountain) in reverse order. The moving set is the connected paper on the grabbed side of the line, plus anything lying on a lifted flap or under a tucked one. Each candidate state is then checked along every crease segment with the taco and tortilla non-crossing tests from flat-folding theory: layers hinged at the same edge must nest rather than interleave, so a fold that would push paper through paper is refused. The puzzle check samples points every few map units along the hidden route and around its destination, and passes when every point is on top of its stack, face up, and all of them sit in one rigid placement on the desk. Any sequence of folds that gets there counts.&lt;/p&gt;
&lt;p&gt;The street plan is drawn in a 960 × 660 map space with a seeded random generator, so the city is the same on every load. The river is a Catmull-Rom spline that widens downstream, with its banks offset from the centreline. The parades, main streets, parks, docks, gasworks and railway are laid by hand, and each of the eight areas between the main roads gets a few named streets. Everything else comes from recursive polygon subdivision: each block is cut across its longest extent with a gap the width of a street, until it falls below a target size set by the part of town it is in. The old town has small blocks cut at loose angles, so its lanes come out crooked; the docks get large, regular ones. Cuts that would leave slivers, fail a roundness test, or run along one of the authored lanes are retried. The hidden walk was drawn first, on the picture the folded sheet shows, and then split back onto the flat sheet, so on the open plan its pieces lie apart.&lt;/p&gt;
&lt;p&gt;Both sides of the sheet are painted onto 2D canvases and used as three.js textures. Labels are placed with oriented-box collision tests and kept off the creases; street names follow curved roads letter by letter, and a placement that would bend a name too sharply is skipped for another spot along the road. Streets the generator made get names from a shuffled pool of about 120. The street index on the reverse is built from the labels that actually landed on the front, with their grid squares. Paper grain, mottling and edge toning are multiplied over both sides.&lt;/p&gt;
&lt;p&gt;Each panel is a subdivided mesh with a front and a back material. The page counts how many times each crease segment has been folded each way, starting with the printer&amp;#39;s folds, and turns that count into a normal map for the crease lines, a wear map that cracks the ink and adds grime along the folds (mixed into the standard material with a small shader patch), and a gentle tenting of the vertices so an opened map doesn&amp;#39;t lie flat. Folded edges get half-cylinder strips for the paper&amp;#39;s thickness, and a directional lamp casts soft shadows on a procedurally drawn wooden desk. The paper sound is synthesised with the Web Audio API: a burst of noise with random crackles, band-passed into the range of a rustle.&lt;/p&gt;
&lt;h2 id=&quot;notes&quot;&gt;Notes&lt;/h2&gt;
&lt;p&gt;There is a false lead on the sheet as well, and the key will show it once you ask. The plan needs WebGL. Adding &lt;code&gt;#lite&lt;/code&gt; to the artifact&amp;#39;s own address lowers the texture sizes, shadow resolution and pixel ratio for slower machines. Type is set in IM Fell English, EB Garamond and Alegreya Sans from Google Fonts.&lt;/p&gt;
&lt;p&gt;This copy fixes the &lt;strong&gt;How to fold&lt;/strong&gt; and &lt;strong&gt;Cartographer’s key&lt;/strong&gt; drawers, which ran about 20 px off the left edge of narrow phones.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Stave</title>
    <link href="https://dogum.github.io/artifact-shelf/a/stave/"/>
    <id>https://dogum.github.io/artifact-shelf/a/stave/</id>
    <published>2026-10-05T12:00:00Z</published>
    <updated>2026-10-05T12:00:00Z</updated>
    <category term="Toys"/>
    <summary>A typeface drawn on twelve tuned strings. Type a line and each letter plays where its strokes end, turn and cross, as plucked strings, bows and bells.</summary>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://dogum.github.io/artifact-shelf/media/stave/poster.webp&quot; alt=&quot;&quot; width=&quot;640&quot;/&gt;&lt;/p&gt;&lt;p&gt;A typeface drawn on twelve tuned strings. Type a line and each letter plays where its strokes end, turn and cross, as plucked strings, bows and bells.&lt;/p&gt;&lt;p&gt;Stave is a typeface and a musical instrument on one page. Its letters are drawn across twelve horizontal strings tuned to a pentatonic scale, and a playhead reads each glyph from left to right, sounding a string wherever the ink ends, turns, runs along it or crosses it. Type, and every new letter plays as it appears.&lt;/p&gt;
&lt;h2 id=&quot;how-to-use-it&quot;&gt;How to use it&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;Click or tap the ruled stage under &lt;strong&gt;Play line&lt;/strong&gt; and type. Each new letter plays as you type it, and &lt;strong&gt;Backspace&lt;/strong&gt; damps every string that is still ringing. Sound starts after your first tap or key press.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Play line&lt;/strong&gt; (or ⌘/Ctrl + Enter) runs the playhead across the whole text. Press it again, or Esc, to stop. &lt;strong&gt;Clear&lt;/strong&gt; empties the stage.&lt;/li&gt;&lt;li&gt;The chips next to &lt;strong&gt;Try&lt;/strong&gt; load and play example lines, several of which show off punctuation: &lt;code&gt;(quietly) and then — silence...&lt;/code&gt;, &lt;code&gt;&amp;lt;swell and &amp;gt;fade&lt;/code&gt;, &lt;code&gt;bdpq qpdb&lt;/code&gt;.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Read&lt;/strong&gt; shows the text. &lt;strong&gt;Score&lt;/strong&gt; marks every sounding point on it: brass dots for melody, red dots on the drone strings, rings for bells, bars for bowed notes and small grey dots for grace notes.&lt;/li&gt;&lt;li&gt;Under &lt;strong&gt;Type settings are the instrument&amp;#39;s controls&lt;/strong&gt;: &lt;strong&gt;Weight&lt;/strong&gt; (heavier ink plays louder and brighter), &lt;strong&gt;Slant&lt;/strong&gt; (italic rolls each chord into an arpeggio), &lt;strong&gt;Tracking&lt;/strong&gt; (the gap between notes), &lt;strong&gt;Reading speed&lt;/strong&gt;, &lt;strong&gt;Ornament&lt;/strong&gt; (from melody only up to a grace note on every string a stroke crosses), &lt;strong&gt;Room&lt;/strong&gt; (dry to hall), and &lt;strong&gt;Tuning&lt;/strong&gt;: Bright, Dusk or Open pentatonic, in any of twelve keys.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Your name has a melody&lt;/strong&gt;: type a name and press &lt;strong&gt;Play name&lt;/strong&gt; or Enter. &lt;strong&gt;Loop&lt;/strong&gt; repeats it, and the strip below plots the tune with its note names.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;The full set&lt;/strong&gt;: tap any of the 52 letters, 10 figures and 39 marks to hear it. The panel beside the grid lists each feature of the glyph and the note it plays.&lt;/li&gt;&lt;li&gt;The &lt;strong&gt;Liner notes&lt;/strong&gt; tab explains the design, with figures you can play.&lt;/li&gt;&lt;/ul&gt;
&lt;h2 id=&quot;how-it-works&quot;&gt;How it works&lt;/h2&gt;
&lt;p&gt;Every glyph is defined in code from three primitives: straight lines, elliptical arcs and cubic Bézier curves, on a grid where one unit of height is one string. The five lines a type designer works between (descender, baseline, x-height, cap height and ascender) are strings, tuned by default to E3, C4, C5, E5 and G5, with seven more strings between them. Because the scale is pentatonic, any two notes sound consonant together. Some letters are generated from others: d is b mirrored left to right, p is b flipped about the middle of the x-height, and q is both, which makes them the retrograde, inversion and retrograde inversion of one phrase. Accented letters fall back to their base form through Unicode decomposition.&lt;/p&gt;
&lt;p&gt;To read a glyph, each stroke is flattened to a polyline and scanned. A stroke end more than 0.22 units from any other stroke is a free terminal and plucks the nearest string. Crests and troughs come from sign changes in the vertical direction along the pen path. A vertical line strums both its ends, a horizontal line lying on a string becomes a bowed note held for its length, and a dot rings a bell. String crossings are found by intersecting every polyline segment with each integer string height; those become quiet grace notes scaled by Ornament. Notes snap to the nearest string and duplicates merge. The baseline and x-height are both C, and nearly every lowercase letter touches them, so those two strings play softly as a drone and the highest note off them leads.&lt;/p&gt;
&lt;p&gt;Horizontal position is time, so the type&amp;#39;s spacing is its rhythm: advance widths, sidebearings and tracking set the gaps between notes, and a word space is a rest. Slant shears each event&amp;#39;s x position by (y − 2.5)·tan(angle), so in italic the foot of a stem sounds before its top and every stem becomes a rising arpeggio. Punctuation works as score markings. A full stop plays a tonic cadence and a rest, a question mark a half cadence on the dominant, parentheses mute what they enclose, quotation marks raise it an octave, &amp;lt; and &amp;gt; swell or fade the next word, and a capital adds a bass note on the downbeat. Playback is a look-ahead scheduler that queues events against the Web Audio clock every 25 ms.&lt;/p&gt;
&lt;p&gt;All sound is synthesized with the Web Audio API, with no samples. Plucks are Karplus–Strong strings rendered in JavaScript at the moment they are scheduled: a burst of low-passed noise, comb-filtered for pick position, circulating in a delay line with a two-point averaging filter and a first-order all-pass for exact tuning, after Jaffe and Smith. Plucking a string again cuts off the note it was holding. Bowed notes are two detuned sawtooth oscillators and a sine through a low-pass filter that opens on the attack, with vibrato that fades in. Bells are two-operator FM. Room mixes in a convolution reverb whose impulse response is synthesized noise that darkens as it decays, and a compressor and limiter keep dense strums from clipping. The stage is drawn on a 2D canvas; the glyph tiles and liner-note figures are SVG built from the same stroke data.&lt;/p&gt;
&lt;h2 id=&quot;notes&quot;&gt;Notes&lt;/h2&gt;
&lt;p&gt;The liner notes include the approaches that were tried and dropped, such as reading letter outlines as waveforms, and credit earlier drawn-sound instruments: Daphne Oram&amp;#39;s Oramics machine, Iannis Xenakis&amp;#39;s UPIC and Evgeny Murzin&amp;#39;s ANS synthesizer. Your text, name and settings are kept in the browser between visits.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Infestation</title>
    <link href="https://dogum.github.io/artifact-shelf/a/infestation/"/>
    <id>https://dogum.github.io/artifact-shelf/a/infestation/</id>
    <published>2026-10-01T12:00:00Z</published>
    <updated>2026-10-01T12:00:00Z</updated>
    <category term="Games"/>
    <summary>A page that draws its own TypeScript source, then lets four species of bug eat it token by token while two spiders hunt them and their genes drift.</summary>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://dogum.github.io/artifact-shelf/media/infestation/poster.webp&quot; alt=&quot;&quot; width=&quot;640&quot;/&gt;&lt;/p&gt;&lt;p&gt;A page that draws its own TypeScript source, then lets four species of bug eat it token by token while two spiders hunt them and their genes drift.&lt;/p&gt;&lt;p&gt;This page is drawn from its own source code, a React and TypeScript component rendered glyph by glyph onto a canvas. Four species of bug live in the text and each eats one kind of token: worms take strings and numbers, weevils keywords, beetles punctuation, moths comments. Nothing eats a type annotation, at least at first. Two kinds of spider hunt the bugs, and every creature carries genes that mutate when it breeds.&lt;/p&gt;
&lt;h2 id=&quot;how-to-use-it&quot;&gt;How to use it&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;Watch the visible part of the file assemble itself, then the bugs arrive. Scroll to see the rest of the file.&lt;/li&gt;&lt;li&gt;Move the cursor over the code. It is a lamp that draws moths, and a loupe magnifies the text under it. &lt;strong&gt;Loupe&lt;/strong&gt; (L) turns the magnifier off.&lt;/li&gt;&lt;li&gt;Click or tap any bug or spider to pin it. Its genes appear on the &lt;strong&gt;Evolution&lt;/strong&gt; tab.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Recompile&lt;/strong&gt; (R) sends every fallen glyph flying back to its place. &lt;strong&gt;Release bugs&lt;/strong&gt; (B) and &lt;strong&gt;Release spiders&lt;/strong&gt; (S) add more. &lt;strong&gt;Pause&lt;/strong&gt; (Space) stops time.&lt;/li&gt;&lt;li&gt;The &lt;strong&gt;Field notes&lt;/strong&gt; panel has three tabs. &lt;strong&gt;Census&lt;/strong&gt; shows population sparklines, a phase plot of bugs against spiders, and how much of the source is still intact. &lt;strong&gt;Evolution&lt;/strong&gt; shows trait ranges per species, any new strains, and a mutation-rate slider from off to 4×. &lt;strong&gt;Field log&lt;/strong&gt; records arrivals, extinctions and egg sacs.&lt;/li&gt;&lt;/ul&gt;
&lt;h2 id=&quot;how-it-works&quot;&gt;How it works&lt;/h2&gt;
&lt;p&gt;A small hand-written tokenizer splits the source into keywords, types, strings, numbers, comments, punctuation and identifiers. Each character becomes a glyph with a home cell, painted once to an offscreen canvas. A glyph is always in one of five states: home, loose, flying, piled or lost. When a bug finishes a bite the glyph is knocked loose, falls under gravity and lands in a heap at the bottom of the window. The heaps follow a sandpile rule: a glyph that lands on a column more than a line taller than its neighbours slides toward the lower side. Recompile flies every glyph home in reading order along an eased arc.&lt;/p&gt;
&lt;p&gt;Bugs forage by sampling random spots within about fourteen character widths and steering toward anything edible, or pick up a scent from elsewhere in the file when nothing is close. Each bite adds energy. A bug that reaches its species&amp;#39; threshold splits in two, and bugs die of hunger or old age. Children inherit speed, size, wariness, a tendency to play dead, camouflage and an appetite for every token kind, each nudged by a Gaussian mutation and clamped to set bounds. Faster, larger and better-camouflaged bugs burn more energy, and nothing else steers the outcome. When a lineage starts eating a food its ancestors never touched, it is logged as a new strain.&lt;/p&gt;
&lt;p&gt;The spiders are state machines. The jumping spider prowls, stalks, crouches and leaps at where its prey is heading, but camouflage shortens how far it can see unless its own acuity gene is high, and prey that notice it either flee or freeze. The orb weaver spins a web and waits; how firmly a bug sticks depends on its species and size, and some pull free. Well-fed spiders lay egg sacs that hatch into mutated young, and spiders turn up on their own once there are enough bugs to feed them.&lt;/p&gt;
&lt;p&gt;The simulation lives in a mutable ref and is stepped and drawn on every animation frame. React only re-renders the side panel, four times a second, from a read-only snapshot of the world, which keeps the 60 fps work out of React state.&lt;/p&gt;
&lt;h2 id=&quot;notes&quot;&gt;Notes&lt;/h2&gt;
&lt;p&gt;The page&amp;#39;s own heading calls it Infestation.tsx. The text you see is the component&amp;#39;s TypeScript source; the page runs a compiled build of it with React bundled in. With reduced motion requested, the file appears already assembled.&lt;/p&gt;
&lt;p&gt;The original was a page fragment; this copy wraps it in a complete HTML document so it runs on its own.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>ORDINAL</title>
    <link href="https://dogum.github.io/artifact-shelf/a/ordinal/"/>
    <id>https://dogum.github.io/artifact-shelf/a/ordinal/</id>
    <published>2026-09-30T12:00:00Z</published>
    <updated>2026-09-30T12:00:00Z</updated>
    <category term="Generative Art"/>
    <summary>Connect-the-dots taken apart into points, numbering and rule: solve and print 21 puzzles, or change the rule and draw times tables, roses and fractals.</summary>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://dogum.github.io/artifact-shelf/media/ordinal/poster.webp&quot; alt=&quot;&quot; width=&quot;640&quot;/&gt;&lt;/p&gt;&lt;p&gt;Connect-the-dots taken apart into points, numbering and rule: solve and print 21 puzzles, or change the rule and draw times tables, roses and fractals.&lt;/p&gt;&lt;p&gt;A connect-the-dots page broken into its working parts: a set of points, a numbering, a rule for which numbers join, and a way of drawing each join, played out over time. Leave the rule at n → n + 1 and you get a book of 21 mystery pictures to solve by tapping, with printable puzzle and solution sheets. Change it to n → 2n on 200 dots around a circle and the same machinery draws a cardioid.&lt;/p&gt;
&lt;h2 id=&quot;how-to-use-it&quot;&gt;How to use it&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;The page opens by drawing Puzzle No. 1 for you. After that, pick any card under &lt;strong&gt;Library → Puzzles&lt;/strong&gt;. The title reads &amp;quot;What is it?&amp;quot; until you finish. Tap the dots in order or drag through them like a pencil; &lt;strong&gt;Z&lt;/strong&gt; steps back and &lt;strong&gt;Enter&lt;/strong&gt; connects the next dot. When you finish, a toast shows your dot count, slips and time.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Mathematics&lt;/strong&gt; holds 15 figures: a times table, Maurer rose, sunflower, star polygon, Lissajous curve, spirograph, Fay&amp;#39;s butterfly, a superformula starfish, the Koch snowflake, Sierpiński arrowhead, dragon and Hilbert curves, a π walk and the Lorenz attractor.&lt;/li&gt;&lt;li&gt;The right-hand panel is the formula, one row per symbol. &lt;strong&gt;P&lt;/strong&gt; sets the number of dots. &lt;strong&gt;σ Numbering&lt;/strong&gt; reorders them (as drawn, shortest tour, sweep, Hilbert, shuffled, reversed). &lt;strong&gt;f Rule&lt;/strong&gt; takes any expression in n, N and k, with chips for n+1, k·n, n+k, n² and N+1−n, a &lt;strong&gt;k&lt;/strong&gt; slider, &lt;strong&gt;Sweep k&lt;/strong&gt; and &lt;strong&gt;wrap mod N&lt;/strong&gt;. &lt;strong&gt;γ Stroke&lt;/strong&gt; joins with line, curve, arc or step. &lt;strong&gt;τ Hand&lt;/strong&gt; switches between &lt;strong&gt;You&lt;/strong&gt;, &lt;strong&gt;Machine&lt;/strong&gt; and &lt;strong&gt;Circles&lt;/strong&gt;.&lt;/li&gt;&lt;li&gt;With the machine drawing, drag the ruler under the paper to scrub τ, or use ← and →. Space plays and pauses, R restarts, F fits the view, and 1, 2, 3 pick a hand. Scroll or pinch to zoom, drag to pan. &lt;strong&gt;View&lt;/strong&gt; toggles Numbers, Dots, Ghost (a faint preview of every join) and Sound.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Make&lt;/strong&gt; turns other things into puzzles: &lt;strong&gt;Type&lt;/strong&gt; (letters or emoji), &lt;strong&gt;Equation&lt;/strong&gt; (x(t), y(t) or r(θ)), &lt;strong&gt;Image&lt;/strong&gt; (a dropped picture, as Outline or One line), &lt;strong&gt;Sketch&lt;/strong&gt; (draw with a finger or mouse) and &lt;strong&gt;Score&lt;/strong&gt; (paste or open a drawing&amp;#39;s JSON).&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Ask&lt;/strong&gt; has Claude draw a subject you describe. On this site it uses your own Anthropic API key: paste it into &lt;strong&gt;Your Anthropic API key&lt;/strong&gt;, pick a model, and requests go straight from your browser to api.anthropic.com, billed to that key. The key is held only for the visit unless you tick &lt;strong&gt;Remember on this device&lt;/strong&gt;, which stores it in this browser&amp;#39;s local storage.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Export&lt;/strong&gt; gives a printable puzzle and a solution sheet (US Letter SVG), a PNG of the stage, the score as JSON, a video of the drawing, or a link that carries the drawing in the address. &lt;strong&gt;Save&lt;/strong&gt; keeps drawings under &lt;strong&gt;Yours&lt;/strong&gt; in this browser. &lt;strong&gt;Theory&lt;/strong&gt; opens six short facts about dots, each with buttons that load a live example.&lt;/li&gt;&lt;/ul&gt;
&lt;h2 id=&quot;how-it-works&quot;&gt;How it works&lt;/h2&gt;
&lt;p&gt;The formula in the header, γ ∘ f ∘ σ(P) with τ ∈ [0, N], is how the code is organised. P is the point set, σ the numbering of those points, f the rule that says which numbers connect, γ how one connection is drawn, and τ the time that plays the connections out. Every drawing is stored as a score: layers of SVG path data, splines, simple shapes, longitude and latitude, equations, L-systems or raw points. Each layer is sampled densely, then reduced to dots with Ramer–Douglas–Peucker, which keeps a point only if dropping it would pull the line more than ε off the true shape, so corners and tips survive at any count. When a layer asks for an exact number of dots, ε is bisected to the largest count within budget, then the closest pairs are thinned and the longest arcs split at their arc-length midpoints until the count is exact.&lt;/p&gt;
&lt;p&gt;Silhouettes made of circles, ellipses, capsules, jointed limbs and polygons are signed distance functions combined with a smooth minimum, traced at their zero contour with marching squares, with true polygon corners snapped back afterwards. Typed text is drawn on a hidden canvas and traced the same way. An uploaded picture becomes a darkness field, thresholded by Otsu&amp;#39;s method and contoured with marching squares; &lt;strong&gt;One line&lt;/strong&gt; instead stipples it by darkness (rejection sampling, then six rounds of Lloyd relaxation toward weighted centroids) and threads every dot on a nearest-neighbour tour improved by 2-opt. Maps use an equirectangular projection about the middle latitude, and L-systems are expanded by string rewriting and walked by a turtle.&lt;/p&gt;
&lt;p&gt;σ is a permutation of the dots: shortest tour uses the same nearest-neighbour and 2-opt tour, sweep sorts by angle around the centroid, Hilbert sorts by position along a Hilbert curve, and shuffled is a seeded Fisher–Yates shuffle. With f = n + 1 the dots are joined as a path. Any other rule is compiled by a small expression parser and drawn as a chord diagram, one chord from each n to f(n), wrapped mod N. A target that is not a whole number lands between two neighbouring dots, which lets &lt;strong&gt;Sweep k&lt;/strong&gt; slide k smoothly: on 200 points around a circle, k = 2 gives a cardioid and k = 3 a nephroid. The sunflower places seed n at radius √n and angle n × 137.5°, the golden angle, and the rule n → n + 34 picks out one family of its Fibonacci spirals. The star polygon {12/5} is n → n + 5 on twelve points.&lt;/p&gt;
&lt;p&gt;γ draws each join as a straight line, a cubic Bézier with Catmull–Rom tangents taken from the neighbouring dots (sharp turns stay sharp), a quadratic arc bowed to one side, or a right-angle step. At τ = k the first k joins are drawn; the machine hand gives each join time in proportion to a blend of its length and the average, so the pen moves at a roughly even speed. &lt;strong&gt;Circles&lt;/strong&gt; resamples the finished path to 512 evenly spaced points (1,024 for long paths), takes a discrete Fourier transform, sorts the terms largest first and redraws the path with a chain of rotating circles; the Circles slider sets how many. Number labels are placed one at a time, each tried at 16 angles around its dot and scored against nearby dots, lines and labels already placed. With Sound on, each dot&amp;#39;s height picks a note from a pentatonic scale and its horizontal position sets the stereo pan.&lt;/p&gt;
&lt;h2 id=&quot;notes&quot;&gt;Notes&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Ask&lt;/strong&gt; sends Claude a description of the score format and gets one back as JSON. With &lt;strong&gt;Careful&lt;/strong&gt; ticked, the page compiles the draft, measures it as a printed puzzle (strokes that cross or touch, numbers printed too close together, dots hidden under filled decoration), writes a coarse text picture of the solved drawing, attaches an image of it, and asks Claude for a revision. &lt;strong&gt;Look again&lt;/strong&gt; runs the same check on the drawing on the stage. The 12 pictures under &lt;strong&gt;Drawn by Claude&lt;/strong&gt; were written with a companion ORDINAL skill. The &lt;strong&gt;From Claude&lt;/strong&gt; shelf and the &lt;strong&gt;Pin to From Claude shelf&lt;/strong&gt; export work only when the page is opened inside Claude, so on this site that shelf stays empty. The π walk and the Lorenz attractor are stored as precomputed points.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Benthos</title>
    <link href="https://dogum.github.io/artifact-shelf/a/benthos-gallery/"/>
    <id>https://dogum.github.io/artifact-shelf/a/benthos-gallery/</id>
    <published>2026-09-28T12:00:00Z</published>
    <updated>2026-09-28T12:00:00Z</updated>
    <category term="Generative Art"/>
    <summary>Thirty-four sea creatures, each a cloud of parametric points from a few dozen lines of trigonometry. Orbit any one, tune its sliders and read its source.</summary>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://dogum.github.io/artifact-shelf/media/benthos-gallery/poster.webp&quot; alt=&quot;&quot; width=&quot;640&quot;/&gt;&lt;/p&gt;&lt;p&gt;Thirty-four sea creatures, each a cloud of parametric points from a few dozen lines of trigonometry. Orbit any one, tune its sliders and read its source.&lt;/p&gt;&lt;p&gt;A bestiary of 34 marine animals, from octopus and nautilus to copepods and sea-urchin larvae, where every animal is a set of points computed from parametric curves. There are no meshes, textures or lights. Brightness comes only from how many points land on the same pixel and how far away they are, and opening any card shows the exact function that drew it.&lt;/p&gt;
&lt;h2 id=&quot;how-to-use-it&quot;&gt;How to use it&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;Scroll the five groups: cephalopods; crustaceans; echinoderms and cnidarians; fish, and one reptile; plankton and larvae. Each card animates in place.&lt;/li&gt;&lt;li&gt;Click a card to open the animal on a larger stage, then drag the canvas to orbit it.&lt;/li&gt;&lt;li&gt;The view buttons jump to preset angles such as ¾, front, side or above. The set varies by animal.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;❚❚&lt;/strong&gt; pauses the animation and &lt;strong&gt;auto-orbit&lt;/strong&gt; toggles the slow spin.&lt;/li&gt;&lt;li&gt;Every animal has its own sliders. The octopus has arm curl, undulation and mantle pulse; the staghorn coral has a branching depth.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;show code&lt;/strong&gt; prints the drawing function. &lt;strong&gt;copy sketch&lt;/strong&gt; copies a standalone p5.js file with the helpers, the camera and your current slider values.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;close ✕&lt;/strong&gt; or Esc returns to the grid.&lt;/li&gt;&lt;/ul&gt;
&lt;h2 id=&quot;how-it-works&quot;&gt;How it works&lt;/h2&gt;
&lt;p&gt;Each animal is one JavaScript function that calls &lt;code&gt;cast(x, y, z, brightness)&lt;/code&gt; a few thousand times. The shapes come from a handful of shared helpers: Catmull-Rom splines through control points for spines and limbs, swept tubes that run a ring of points along a path using a frame built from the path&amp;#39;s tangent, flat blades for fins and paddles, and a deterministic hash in place of &lt;code&gt;Math.random&lt;/code&gt; so every frame is repeatable. Time enters as a phase inside the sines, which is how arms coil, fins ripple and bells pulse.&lt;/p&gt;
&lt;p&gt;Some animals carry real geometry. The nautilus shell is a logarithmic spiral, r = A·e^(bθ), with a tube radius of tanh(πb)·r, which keeps each whorl tangent to the one inside it at any tightness. The shrimp&amp;#39;s five pairs of swimmerets share one beat function offset by 1.15 radians per pair, producing a metachronal wave. The staghorn coral is a recursive function in which each branch spawns two or three shorter children at angles drawn from a hash of its own seed.&lt;/p&gt;
&lt;p&gt;The renderer is a small software rasterizer on a 2D canvas. Each point is rotated by the orbit yaw and pitch, projected orthographically, and blended into floating-point RGB buffers. Its colour is interpolated between a near tint and a far tint by depth, and every hit pushes the pixel further toward that colour, so dense regions read bright and sparse ones faint. Grid tiles redraw every third frame and only while on screen, tracked with an IntersectionObserver.&lt;/p&gt;
&lt;h2 id=&quot;notes&quot;&gt;Notes&lt;/h2&gt;
&lt;p&gt;The source panel reads the function with &lt;code&gt;Function.prototype.toString()&lt;/code&gt;, so the code shown is always the code running. The same species functions, copied verbatim, populate the playable Benthos reef elsewhere on this shelf.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Masis &amp; Sis</title>
    <link href="https://dogum.github.io/artifact-shelf/a/masis/"/>
    <id>https://dogum.github.io/artifact-shelf/a/masis/</id>
    <published>2026-09-23T12:00:00Z</published>
    <updated>2026-09-23T12:00:00Z</updated>
    <category term="Generative Art"/>
    <summary>Ararat&#39;s two peaks, Masis and Sis, rebuilt from real elevation data and drawn live in six print styles, from engraved ridgelines to risograph and woodcut.</summary>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://dogum.github.io/artifact-shelf/media/masis/poster.webp&quot; alt=&quot;&quot; width=&quot;640&quot;/&gt;&lt;/p&gt;&lt;p&gt;Ararat&amp;#39;s two peaks, Masis and Sis, rebuilt from real elevation data and drawn live in six print styles, from engraved ridgelines to risograph and woodcut.&lt;/p&gt;&lt;p&gt;Mount Ararat, called Masis in Armenian, and its smaller neighbour Sis, seen from Yerevan and drawn from a real elevation grid embedded in the page. A perspective camera and hidden-line removal turn the heights into a print, and six styles reuse the same depth information: Survey, Topo, Nocturne, Stipple, Risograph and Woodcut. Everything is rendered in the browser with plain Canvas 2D, and any view can be saved as a 3000×1000 header image.&lt;/p&gt;
&lt;h2 id=&quot;how-to-use-it&quot;&gt;How to use it&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;Pick a style from the six tiles under the picture.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Camera&lt;/strong&gt;: Orbit, Altitude, Zoom, Relief, Pan ↔ and Pan ↕.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Light&lt;/strong&gt;: Direction and Height of the light, Snowline, and Sun height for the sun or moon disc.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Ink &amp;amp; detail&lt;/strong&gt;: Line gap, Weight, and the paper, ink and accent colours.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Ornaments&lt;/strong&gt;: Sun / moon, Network, Labels, and Photo guide, which marks where an X / Twitter profile picture would cover a header. The guide is never included in the saved image.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;▶ Orbit&lt;/strong&gt; swings the camera slowly back and forth. &lt;strong&gt;Reseed&lt;/strong&gt; changes the random parts (stars, stipple, paper grain). &lt;strong&gt;Reset style&lt;/strong&gt; restores the preset. &lt;strong&gt;Copy settings&lt;/strong&gt; copies every parameter as JSON.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Save PNG · 3000×1000&lt;/strong&gt; renders the full-size image. Outside claude.ai it opens in a dialog, where you right-click or long-press to save.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;◐ theme&lt;/strong&gt; switches the page between light and dark.&lt;/li&gt;&lt;/ul&gt;
&lt;h2 id=&quot;how-it-works&quot;&gt;How it works&lt;/h2&gt;
&lt;p&gt;The terrain is a 512×512 grid of SRTM-derived elevation from AWS Terrain Tiles, about 240 m per sample, stored in the page as base64-encoded 16-bit heights. For each view the grid is resampled with bilinear interpolation into a new grid aligned with the line of sight from Yerevan and rotated by the orbit angle, so that its rows run away from the viewer. Central-difference surface normals give a Lambert shade for the chosen light direction, and a snow mask combines height above the snowline with a slope test.&lt;/p&gt;
&lt;p&gt;Hidden lines are removed with a floating horizon. Rows are projected near to far through a perspective camera, and each pixel column remembers the highest point drawn so far; a later row is drawn only where it rises above that horizon. The same pass fills a buffer recording which terrain row owns each pixel, a simple G-buffer, so any style can look up height, shade and snow at any pixel.&lt;/p&gt;
&lt;p&gt;Each style reads that buffer differently. Survey, Nocturne and Woodcut draw ridgelines whose opacity and width follow shade and snow, batched into Path2D buckets by alpha and width. Topo runs marching squares over the heights at a 40 m interval at the default line gap, projects the contour segments, keeps only the visible ones, and draws every fifth line heavier. Stipple places jittered dots with a probability set by how dark the pixel is. Risograph composites two spot-colour layers with a rotated halftone screen and a few pixels of misregistration. Woodcut fills the mountain solid and carves paper-coloured lines that widen where the light is strongest.&lt;/p&gt;
&lt;p&gt;The paper texture is five octaves of value noise plus grain and a vignette. While a slider moves, the picture renders at reduced resolution, and the full-quality pass follows about a quarter of a second after it stops.&lt;/p&gt;
&lt;h2 id=&quot;notes&quot;&gt;Notes&lt;/h2&gt;
&lt;p&gt;Elevation: AWS Terrain Tiles (SRTM and other public sources). Peak labels use Noto Serif Armenian from Google Fonts. The offline Python version of this pipeline, along with photographic and painted renders, is in the procedural-art repository linked above.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Shortest-Path Bound Explorer</title>
    <link href="https://dogum.github.io/artifact-shelf/a/shortest-path-bound-explorer/"/>
    <id>https://dogum.github.io/artifact-shelf/a/shortest-path-bound-explorer/</id>
    <published>2026-09-23T12:00:00Z</published>
    <updated>2026-09-23T12:00:00Z</updated>
    <category term="Explainers"/>
    <summary>An interactive field guide to the C-HD shortest-path bound: term-by-term sliders, growth charts, a 3D win map and Dijkstra races on real street grids.</summary>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://dogum.github.io/artifact-shelf/media/shortest-path-bound-explorer/poster.webp&quot; alt=&quot;&quot; width=&quot;640&quot;/&gt;&lt;/p&gt;&lt;p&gt;An interactive field guide to the C-HD shortest-path bound: term-by-term sliders, growth charts, a 3D win map and Dijkstra races on real street grids.&lt;/p&gt;&lt;p&gt;A long, hands-on page about one formula: the runtime bound O(n + m + m·log(2 + m/(n+1)) + m⅓·(n·log(n+2))⅔) for C-HD, a directed single-source shortest-path algorithm that a September 2026 Vals AI writeup describes as designed by Claude agents and proved in Lean. Eleven sections take the bound apart term by term, set it against Dijkstra and the 2025–2026 Duan et al. bounds, and show where its formula comes out ahead with constants set to 1: a narrow band of sparse graphs, and on its own showcase profile only at astronomically large n.&lt;/p&gt;
&lt;h2 id=&quot;how-to-use-it&quot;&gt;How to use it&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;01 Anatomy:&lt;/strong&gt; drag &lt;code&gt;vertices n&lt;/code&gt; and &lt;code&gt;avg degree d&lt;/code&gt;. The bar splits the predicted operation count into its three terms, and the leaderboard compares every algorithm at that graph size. Hover a term in the formula to highlight it in the bar.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;02 Growth race:&lt;/strong&gt; switch between &lt;code&gt;vary n (sparse → huge)&lt;/code&gt;, &lt;code&gt;vary density&lt;/code&gt; and &lt;code&gt;certified profile (astronomical n)&lt;/code&gt; to see overhead over linear time as the graph grows.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;03 Exponent race:&lt;/strong&gt; press &lt;code&gt;▶ play the history&lt;/code&gt;, or tap a year on the timeline, to add each bound from Bellman–Ford (1956–58) to C-HD.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;04 Zoom out:&lt;/strong&gt; keep scrolling. Each frame adds more zeros on a doubly logarithmic axis, out to n ≈ 10^54,000, while a gauge tracks C-HD against Fibonacci-heap Dijkstra.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;05 Who wins where:&lt;/strong&gt; click a cell on the map to load that graph shape into section 01. In the 3D landscape below it, drag to orbit, scroll or pinch to zoom, and tick &lt;code&gt;apply certified range&lt;/code&gt; to drop the ground where C-HD falls back to Bellman–Ford.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;06–09 races:&lt;/strong&gt; &lt;code&gt;▶ play&lt;/code&gt;, &lt;code&gt;step&lt;/code&gt;, &lt;code&gt;reset&lt;/code&gt; and &lt;code&gt;new graph&lt;/code&gt; drive Dijkstra and band relaxation side by side; the &lt;code&gt;band width Δ&lt;/code&gt; slider moves between Dijkstra and Bellman–Ford behaviour. Section 07 steps through a model of C-HD with &lt;code&gt;size limit k&lt;/code&gt; and &lt;code&gt;levels&lt;/code&gt;. Section 09 offers &lt;code&gt;Savannah · grid&lt;/code&gt;, &lt;code&gt;Boston · tangle&lt;/code&gt; and &lt;code&gt;Paris · star&lt;/code&gt;; tap the map to move the start, and choose &lt;code&gt;race by rounds&lt;/code&gt; or &lt;code&gt;race by work&lt;/code&gt;.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;10 Live benchmark:&lt;/strong&gt; pick an average degree and a maximum n, press &lt;code&gt;run sweep&lt;/code&gt;, then &lt;code&gt;copy CSV&lt;/code&gt; or &lt;code&gt;copy markdown&lt;/code&gt;. The 1M setting is slow.&lt;/li&gt;&lt;/ul&gt;
&lt;h2 id=&quot;how-it-works&quot;&gt;How it works&lt;/h2&gt;
&lt;p&gt;Most of the charts evaluate textbook running-time formulas with every constant set to 1 and logs in base 2: Dijkstra with a binary heap, (n+m)·log n; with a Fibonacci heap, m + n·log n; a d-ary heap; Duan, Mao, Mao, Shu and Yin&amp;#39;s 2025 m·log⅔ n; the 2026 Duan, Mao, Shu, Yin bound; Bellman–Ford, nm; and BFS as a floor. C-HD&amp;#39;s formula is used only inside its certified range, m ≤ n·⌊⌊log₂n⌋¾⌋, and Bellman–Ford is charged outside it. The growth chart works in (log n, d) rather than n so it can run far past double-precision numbers. The exponent race sets the average degree to logα n and plots the remaining power of log n per vertex, which turns the &amp;quot;sorting barrier&amp;quot; into a flat line at 1.&lt;/p&gt;
&lt;p&gt;The barrier comes from Dijkstra&amp;#39;s algorithm settling vertices one at a time in exact distance order, which sorts them as a side effect. The newer algorithms avoid full ordering: bounded local searches from the frontier, a heap kept only over a thinned set of pivot vertices, and recursion in bounded batches. The page uses Δ-stepping, which relaxes every tentative distance in a band of width Δ together, as a simpler stand-in for that idea in the animated races.&lt;/p&gt;
&lt;p&gt;Section 07 runs a scaled-down model of C-HD&amp;#39;s FindPivots-HD step (bounded searches with a size limit, unexplored leaves counted against it, contact merges, permanent edge deletion) inside a Duan-et-al.-style bounded recursion, and checks each run against Dijkstra. It is not the Lean-verified program, which runs Bellman–Ford on any graph under 65,536 vertices. The street maps are OpenStreetMap snapshots contracted to intersections, with one-way streets honoured and trimmed to the largest strongly connected component. The benchmark builds random directed graphs in compressed sparse row form, runs binary-heap Dijkstra, Δ-stepping, queue-based Bellman–Ford and BFS, checks that the distances agree, and plots nanoseconds per edge. The 3D landscape is drawn with three.js.&lt;/p&gt;
&lt;h2 id=&quot;notes&quot;&gt;Notes&lt;/h2&gt;
&lt;p&gt;Constants of 1 make the crossings a statement about growth rates, not stopwatch time, and the page notes that C-HD&amp;#39;s real constants are large. The C-HD bound comes from a blog post with a machine-checked proof, not a peer-reviewed paper. Other sources cited on the page: arXiv 2504.17033, 2602.07868 and 2511.03007. Road data © OpenStreetMap contributors, ODbL.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Benthos reef</title>
    <link href="https://dogum.github.io/artifact-shelf/a/benthos-reef/"/>
    <id>https://dogum.github.io/artifact-shelf/a/benthos-reef/</id>
    <published>2026-09-22T12:00:00Z</published>
    <updated>2026-09-22T12:00:00Z</updated>
    <category term="Games"/>
    <summary>A one-minute predator-and-prey game on a reef of point-cloud sea animals. Pick one of six species, eat what it eats and hide from what hunts it.</summary>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://dogum.github.io/artifact-shelf/media/benthos-reef/poster.webp&quot; alt=&quot;&quot; width=&quot;640&quot;/&gt;&lt;/p&gt;&lt;p&gt;A one-minute predator-and-prey game on a reef of point-cloud sea animals. Pick one of six species, eat what it eats and hide from what hunts it.&lt;/p&gt;&lt;p&gt;A small reef built from the same point-cloud animals as the Benthos bestiary, turned into a game of eating and hiding. Each round lasts sixty seconds: you play one animal, eat whatever it can eat, and stay out of reach of whatever hunts it. Everything else on the reef, from copepod swarms to sharks and manta rays, is running the same food web at the same time.&lt;/p&gt;
&lt;h2 id=&quot;how-to-use-it&quot;&gt;How to use it&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;Under &lt;strong&gt;Play as&lt;/strong&gt;, choose an animal. Each has one move: Lionfish &lt;strong&gt;Flare&lt;/strong&gt;, Clownfish &lt;strong&gt;Home&lt;/strong&gt;, Pufferfish &lt;strong&gt;Inflate&lt;/strong&gt;, Octopus &lt;strong&gt;Ink&lt;/strong&gt;, Moray eel &lt;strong&gt;Lunge&lt;/strong&gt;, Sea turtle &lt;strong&gt;Tuck&lt;/strong&gt;.&lt;/li&gt;&lt;li&gt;Under &lt;strong&gt;Reef&lt;/strong&gt;, choose a level. &lt;strong&gt;Morning&lt;/strong&gt;, &lt;strong&gt;Noon&lt;/strong&gt;, &lt;strong&gt;Dusk&lt;/strong&gt; and &lt;strong&gt;Midnight&lt;/strong&gt; open in order as you clear each one, with rising points goals and more or different hunters.&lt;/li&gt;&lt;li&gt;Press &lt;strong&gt;Dive in&lt;/strong&gt;.&lt;/li&gt;&lt;li&gt;Keyboard: arrow keys or WASD to steer, Space to sprint, E for your animal&amp;#39;s move, and 1, 2 and 3 for the &lt;strong&gt;Chase&lt;/strong&gt;, &lt;strong&gt;Side&lt;/strong&gt; and &lt;strong&gt;Top&lt;/strong&gt; cameras.&lt;/li&gt;&lt;li&gt;Touch: drag anywhere to steer with an on-screen stick, hold &lt;strong&gt;dash&lt;/strong&gt; to sprint, and press the move button for the ability.&lt;/li&gt;&lt;li&gt;Coral, the caves under the rock arches, and anemones are hiding places. Which ones you fit depends on your size, and only a clownfish is safe in an anemone. Banners at the top tell you when something is after you and when you are hidden.&lt;/li&gt;&lt;li&gt;Reaching the goal earns one star, half again the goal earns a second, and not being eaten earns the third. Stars are kept in this browser.&lt;/li&gt;&lt;li&gt;Sound starts off. The &lt;strong&gt;off&lt;/strong&gt; button in the top corner turns it on.&lt;/li&gt;&lt;/ul&gt;
&lt;h2 id=&quot;how-it-works&quot;&gt;How it works&lt;/h2&gt;
&lt;p&gt;The animals are the bestiary&amp;#39;s own drawing functions, included verbatim. While the menu loads, the game runs each function at 8 to 16 points in its swim or pulse cycle and packs the point positions into RGBA32F float textures, about 390,000 points per keyframe across 26 species, plus the sand, rock arches, boulders and drifting marine snow. To hide the jump where a cycle wraps, each keyframe is cross-faded with its twin one period earlier.&lt;/p&gt;
&lt;p&gt;Drawing uses WebGL 2 with no vertex buffers. The vertex shader takes &lt;code&gt;gl_VertexID&lt;/code&gt;, fetches that point from the texture with &lt;code&gt;texelFetch&lt;/code&gt;, interpolates between the two nearest keyframes, and places it using the animal&amp;#39;s position and rotation. Point size scales with distance, colour moves between a near and far tint by depth, and exponential fog fades the far reef into the water colour. The pufferfish has a second baked set for its inflated shape, and the shader blends between the two.&lt;/p&gt;
&lt;p&gt;Every creature moves by Reynolds-style steering. Each frame it works out a desired velocity (seek prey, flee threats, wander between waypoints near a home, push away from shelters it cannot enter) and turns toward it with a capped acceleration. Predators lock onto the nearest visible prey within sensing range, drop targets that hide or turn out to be protected, and rest for a few seconds after a kill. Jellyfish and siphonophores sting small animals that drift beneath them; sea turtles are immune and eat the jellyfish.&lt;/p&gt;
&lt;p&gt;All sound is synthesised with the Web Audio API: low-pass-filtered brown noise for the sea, short oscillator sweeps for bites and moves, and a heartbeat that quickens as a hunter closes in.&lt;/p&gt;
&lt;h2 id=&quot;notes&quot;&gt;Notes&lt;/h2&gt;
&lt;p&gt;Needs a browser with WebGL 2. Preparing the reef takes a few seconds before &lt;strong&gt;Dive in&lt;/strong&gt; becomes available. The &lt;strong&gt;Save result card&lt;/strong&gt; button only appears where the claude.ai downloads feature is available.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Mirror Cube Solver</title>
    <link href="https://dogum.github.io/artifact-shelf/a/mirror-cube-solver/"/>
    <id>https://dogum.github.io/artifact-shelf/a/mirror-cube-solver/</id>
    <published>2026-09-19T12:00:00Z</published>
    <updated>2026-09-19T12:00:00Z</updated>
    <category term="Tools"/>
    <summary>Paint a mirror cube&#39;s sticker thicknesses onto a net and get a turn-by-turn solution, played out on a 3D model built to the cube&#39;s real shape.</summary>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://dogum.github.io/artifact-shelf/media/mirror-cube-solver/poster.webp&quot; alt=&quot;&quot; width=&quot;640&quot;/&gt;&lt;/p&gt;&lt;p&gt;Paint a mirror cube&amp;#39;s sticker thicknesses onto a net and get a turn-by-turn solution, played out on a 3D model built to the cube&amp;#39;s real shape.&lt;/p&gt;&lt;p&gt;A solver for the mirror cube, the 3×3 twisty puzzle whose pieces are all one colour and differ only in how far they stick out. You describe the scramble by thickness instead of colour, and it gives back a list of turns, shown one at a time on a 3D model that takes the same lumpy shape as the cube in your hand.&lt;/p&gt;
&lt;h2 id=&quot;how-to-use-it&quot;&gt;How to use it&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;Under &lt;strong&gt;Your cube&amp;#39;s thickness levels&lt;/strong&gt;, pick how many levels you can tell apart. Two (thin and thick) suits most cubes; it goes up to six.&lt;/li&gt;&lt;li&gt;Hold the cube with one face toward you as &lt;strong&gt;Front&lt;/strong&gt; and keep it that way. Choose a level from the palette, then click stickers on the net to paint them. Start with the six outlined centres: setting one fills in its opposite. Clicking a sticker again with the same level clears it.&lt;/li&gt;&lt;li&gt;Hover a sticker to highlight it, and the other stickers on the same piece, on the 3D model.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Fill what&amp;#39;s forced&lt;/strong&gt; fills every sticker that has only one possible answer. &lt;strong&gt;Demo scramble&lt;/strong&gt;, &lt;strong&gt;Fill as solved&lt;/strong&gt; and &lt;strong&gt;Start fresh&lt;/strong&gt; load test states.&lt;/li&gt;&lt;li&gt;Press &lt;strong&gt;Solve it&lt;/strong&gt;, then step with &lt;strong&gt;Next move ▶&lt;/strong&gt; and &lt;strong&gt;◀ Back&lt;/strong&gt;, or press &lt;strong&gt;▶︎&lt;/strong&gt; to play straight through. On a keyboard: → for the next move, ← to go back, space to replay the current turn.&lt;/li&gt;&lt;li&gt;Drag the 3D view to turn it over; pinch or scroll to zoom. &lt;strong&gt;Other side&lt;/strong&gt; flips it, and when the face you need to turn is out of sight that button becomes &lt;strong&gt;Show that face&lt;/strong&gt;.&lt;/li&gt;&lt;/ul&gt;
&lt;h2 id=&quot;how-it-works&quot;&gt;How it works&lt;/h2&gt;
&lt;p&gt;The cube is modelled at the piece level: a position and orientation for each of the 8 corners and 12 edges, with every face turn stored as a permutation and applied by composition. Thickness levels stand in for colours, but with only two levels many pieces look alike, so one set of entries can describe several real cube states. The app enumerates corner and edge assignments by backtracking, discards any that break the cube&amp;#39;s invariants (corner twists summing to a multiple of three, an even number of flipped edges, matching corner and edge permutation parity), keeps up to 14 candidates with the most pieces already home, solves each, and shows the shortest. &lt;strong&gt;Fill what&amp;#39;s forced&lt;/strong&gt; runs the same search with blanks left open and fills only the stickers on which every consistent state agrees.&lt;/p&gt;
&lt;p&gt;The solver follows the layer-by-layer method a person would use. The bottom cross comes from a breadth-first search over a packed coordinate of the four cross edges (24⁴ states), so that stage is optimal. Each of the four first-two-layer pairs is found with Dijkstra&amp;#39;s algorithm over short macro moves such as R U R′, searching a 576-state key that tracks only that pair&amp;#39;s corner and edge. The last layer is solved in two phases, orient then permute, from shortest-path lookup tables built once from a short list of standard last-layer algorithms. A final pass cancels and merges consecutive turns of the same face, including across stage boundaries.&lt;/p&gt;
&lt;p&gt;The 3D model is drawn with three.js. A mirror cube&amp;#39;s cuts sit at fixed planes either side of the core and each piece sticks out by its own thickness, which forces opposite faces to add up to the same depth. The model is built from that rule, with procedurally drawn brushed-metal textures and thicker levels tinted warmer so they read at a glance. Each move is animated with an arrow and a plain-language hint, such as &amp;quot;the front column of the right layer lifts up&amp;quot;.&lt;/p&gt;
&lt;h2 id=&quot;notes&quot;&gt;Notes&lt;/h2&gt;
&lt;p&gt;Turns use standard notation, read from how you are holding the cube: U, D, L, R, F and B, with ′ for counter-clockwise and 2 for a half turn. Set six levels and it works for an ordinary 3×3 as well, with each colour standing in for a level. Your entries are kept in the browser between visits.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Forced Blowup for Navier–Stokes</title>
    <link href="https://dogum.github.io/artifact-shelf/a/navier-stokes-forced-blowup/"/>
    <id>https://dogum.github.io/artifact-shelf/a/navier-stokes-forced-blowup/</id>
    <published>2026-09-09T12:00:00Z</published>
    <updated>2026-10-08T12:00:00Z</updated>
    <category term="Explainers"/>
    <summary>The mathematics behind the 2026 forced blowup results for Navier–Stokes: Clay&#39;s four statements, the BKM criterion, a collapsing vortex and a ladder.</summary>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://dogum.github.io/artifact-shelf/media/navier-stokes-forced-blowup/poster.webp&quot; alt=&quot;&quot; width=&quot;640&quot;/&gt;&lt;/p&gt;&lt;p&gt;The mathematics behind the 2026 forced blowup results for Navier–Stokes: Clay&amp;#39;s four statements, the BKM criterion, a collapsing vortex and a ladder.&lt;/p&gt;&lt;p&gt;An explainer on finite-time blowup for the 3D incompressible Navier–Stokes equations, written around the September 2026 preprints that construct singularities with a smooth external force. It sets out what the Clay problem&amp;#39;s four statements ask, why a force changes the question, how the vortex and multiscale constructions work, and what is still open. Seven figures compute their numbers from the equations printed beside them.&lt;/p&gt;
&lt;h2 id=&quot;how-to-use-it&quot;&gt;How to use it&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;The section bar along the top, &lt;code&gt;01 The question&lt;/code&gt; through &lt;code&gt;11 Still open&lt;/code&gt; and &lt;code&gt;Sources&lt;/code&gt;, jumps between sections. The &lt;code&gt;◐&lt;/code&gt; button switches between light and dark.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Fig. 1, Burgers&amp;#39; equation:&lt;/strong&gt; drag &lt;code&gt;viscosity ν&lt;/code&gt; to zero and &lt;code&gt;max |∂ₓu|&lt;/code&gt; climbs toward a finite-time singularity; raise it and the slope levels off. &lt;code&gt;Pause&lt;/code&gt; and &lt;code&gt;Reset&lt;/code&gt; control the run.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Fig. 3, Beale–Kato–Majda:&lt;/strong&gt; set &lt;code&gt;growth rate α&lt;/code&gt; and &lt;code&gt;time to T&lt;/code&gt;, or press &lt;code&gt;α = ½&lt;/code&gt;, &lt;code&gt;α = 1&lt;/code&gt; or &lt;code&gt;core of §06&lt;/code&gt;. The readout shows whether the vorticity integral stays finite and gives the verdict.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Fig. 4, the Burgers vortex:&lt;/strong&gt; drag &lt;code&gt;strain a&lt;/code&gt; and &lt;code&gt;viscosity ν&lt;/code&gt; and watch the core radius, peak swirl and centre vorticity change while the core stays steady.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Fig. 5, the self-similar core:&lt;/strong&gt; drag &lt;code&gt;anisotropy h&lt;/code&gt; and &lt;code&gt;time to blowup τ&lt;/code&gt; and read the peak speed, core energy, aspect ratio and volume. &lt;code&gt;Pause&lt;/code&gt; and &lt;code&gt;Restart&lt;/code&gt; control the animation.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Fig. 6, the multiscale ladder:&lt;/strong&gt; set &lt;code&gt;stages k&lt;/code&gt;, &lt;code&gt;time t&lt;/code&gt; and &lt;code&gt;frequency ratio&lt;/code&gt;, and compare the bounded field with its runaway slope.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;The timeline (§09):&lt;/strong&gt; filter by &lt;code&gt;Navier–Stokes&lt;/code&gt;, &lt;code&gt;Euler&lt;/code&gt; or &lt;code&gt;Model equations&lt;/code&gt;, and tick &lt;code&gt;proofs only&lt;/code&gt; to hide numerical work.&lt;/li&gt;&lt;/ul&gt;
&lt;h2 id=&quot;how-it-works&quot;&gt;How it works&lt;/h2&gt;
&lt;p&gt;The page starts from equation (1), ∂ₜu + (u·∇)u = νΔu − ∇p + f with ∇·u = 0, and the Clay description&amp;#39;s four statements: (A) and (B) ask for global smooth solutions with the force set to zero, (C) and (D) ask for a breakdown and allow a smooth force. A forced construction defines the force as the residual of a designed flow, so the whole difficulty is keeping that residual smooth through the singular time.&lt;/p&gt;
&lt;p&gt;Fig. 1 integrates Burgers&amp;#39; equation, uₜ + (u²/2)ₓ = ν·uₓₓ, from sin x on a periodic 1,024-cell grid with a finite-volume scheme (Rusanov flux, minmod limiter, explicit diffusion). Fig. 3 uses the model growth ‖ω‖∞ = (T − t)^(−α) and integrates it in closed form, which shows the Beale–Kato–Majda threshold at α = 1. Fig. 4 advects fluid parcels in the exact Burgers vortex, u_θ = Γ/(2πr)·(1 − e^(−r²/r_c²)) with r_c = √(4ν/a), the steady balance between vortex stretching and viscosity.&lt;/p&gt;
&lt;p&gt;Fig. 5 draws the contracting core of the Navier–Stokes construction from its scaling exponents: radius τ^(1/2), height τ^(1/2−h), peak speed τ^(−1/2−h) and core energy τ^(1/2−3h), so the speed diverges while the energy goes to zero. Fig. 6 is a one-dimensional caricature of the Córdoba–Martínez-Zoroa ladder: sine waves at lacunary frequencies whose amplitudes grow from N^−6 at t = 0 to N^(−1+ε) at t = 1, with the norms measured from the samples. The hero background is a canvas particle field following an inward spiral that speeds up as the radius shrinks.&lt;/p&gt;
&lt;h2 id=&quot;notes&quot;&gt;Notes&lt;/h2&gt;
&lt;p&gt;The September 2026 results are preprints and had not been refereed when this was written. Theorem statements are restated from the papers, page counts and section numbers were checked against the PDFs, and every entry in the timeline links to its journal or arXiv record.&lt;/p&gt;
&lt;p&gt;This version replaces an earlier one that also covered the public dispute over credit around the announcements. That material is gone; the page now covers the mathematics only.&lt;/p&gt;</content>
  </entry>
</feed>
