BHmath · v0.1

The math under the cells.

Every glyph in VHX sits on a derivable grid. Every motion follows a published curve. Every contrast ratio is computed, not eyeballed. This page documents the engine — nine primitives, one source file, no hidden constants.

module
VHX_MATH
source
/assets/math-engine.js
deps
none
surface
9 primitives, 26 functions
determinism
total · noise is sin-summed at golden frequencies
runtime
∼3 KB · pure JS · runs in any Worker
§01

Cell geometry. The grid is a coordinate system.

cellW · cellH · snapCols

In a monospace face, every glyph occupies an identical advance-width. The cell — not the pixel — is the layout unit. Width is derived empirically from the chosen face; for Geist Mono on Chrome it lands at 0.602 × fontSize, which means a 14px body line is 8.43px wide per glyph and 21px tall.

Resize the slider to watch the viewport snap to whole cells. The readout shows columns, slack pixels, and the precise cell width. Slack should never be styled; it's the cost of a discrete grid in a continuous world.

derivation · advance ratio
const ADVANCE_RATIO = 0.602;     // measured · Geist Mono · Chrome 120
cellW(fs) = fs × 0.602
cellH(fs) = fs × 1.5           // line-height
cols(V,fs) = ⌊V / cellW(fs)⌋
slack(V,fs) = V − cols × cellW(fs)
Cell snap · live— cols · — slack
480px
14px
§02

Reflow probability. When does a row break?

reflowCritical · reflowBreakProb

Given N text spans of widths w₁..wₙ packed into a row with gap g, the row breaks at the critical viewport V* = Σwᵢ + (N-1)g. Below V*, breakage is certain; above it, fit is certain. Between, the curve is logistic with width equal to one cell.

This isn't a heuristic — it's the curve that minimizes squared error over discrete glyph rounding. Drag the viewport to see the probability cross 0.5 exactly at V*. The orange line is the probability; the dotted line is the critical threshold.

derivation · logistic break
V* = Σwᵢ + (N−1) · g                  // critical viewport
p_break(V) = 1 / (1 + exp((V − V*) / cell))

p(V*) = 0.5                            // exact
p(V* − cell) ≈ 0.731
p(V* + cell) ≈ 0.269
Reflow curve · liveV* = 320 · p = 0.50
320px
4 spans
§03

Contrast. WCAG luminance, no shortcuts.

relLuminance · contrastRatio

Per WCAG 2.1 §1.4.3: gamma-decode each sRGB channel, apply 0.2126·R + 0.7152·G + 0.0722·B, then take the ratio (L₁ + 0.05) / (L₂ + 0.05). AA passes at ≥4.5; AAA at ≥7. Below the threshold the cell is dimmed.

§04

Easing curves. The vocabulary of motion.

Easing · 9 functions

All take t ∈ [0,1] and return [0,1]. smoothstep is Hermite-3, the cheapest curve with zero-derivative endpoints. smootherstep is Perlin's quintic, used when second-derivative continuity matters. The spring is critically-damped — no overshoot, τ sets the response time.

§05

Three-octave noise. The water engine.

noise3(x, t)

The "water" effect across VHX is not Perlin and not random — it's three sine waves summed at golden-ratio frequencies. The result is bounded in [-1,1], smooth in both x and t, and reproducible to machine precision for any (x,t).

Why golden? Because φ is the irrational that takes the longest to reveal a repeat — the sum looks aperiodic over a single browser session even though it cycles in O(2π·φ²).

derivation · 3-octave sine
φ = (1 + √5) / 2 ≈ 1.618033988…

n(x,t) = sin(x       + t)
       + sin(xφ      + tφ·0.7) · 0.5
       + sin(xφ²     + tφ²·0.4) · 0.25

return n / 1.75                        // bound to [−1, 1]
§06

Glyph ramps. Continuous → discrete.

quantize · 4 ramps

To render a value v ∈ [0,1] as a glyph, pick a ramp and quantize: quantize(v, ramp) = ramp[⌊v · ramp.length⌋]. Drag the slider to see each ramp resolve. Ramps are ordered light → dark, sparse → dense.

Ramp probe · livev = 0.50
0.500
§07

4D rotation. The tesseract math.

rotXW · rotYW · project4to2

A tesseract has 16 vertices at {±1}⁴. To draw it on a 2D canvas: rotate in the XW and YW planes (this is what gives 4D its characteristic "inside-out" pulse), project to 3D by dividing by (d₄ − w), then to 2D by dividing through Z.

Two cubes always — the inner and outer cube swap as w rotates through ±1, threading the 8 connecting edges through a continuous torus path. The math is below; the live render runs at the sketch on the right.

derivation · 4d → 2d
verts = {±1}⁴                       // 16 vertices
edges = 32                          // pairs differing in 1 coord

p ← rotXW(p, αt)
p ← rotYW(p, βt)
p3 = (p.xyz) / (d₄ − p.w)
p2 = (p3.xy)  / (d₃ − p3.z)
§08

Surface area. Every export, in one place.

26 functions
groupfunctionsignaturecost