facett-core 0.3.0

facett — visual kernel: render a node/edge Scene into egui (wgpu fast path to come)
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
//! **The "cyber-toon" decoration kernel** — domain-agnostic, pure-CPU L0 beauty
//! helpers that turn a flat instance graph into a luminous, animated dashboard
//! **with zero GPU / vello dependency**, so they light up identically native AND
//! in the wasm demo. The graph/map skins (and the population showcase) compose
//! these over the [`prim`](super::prim) instances they already lower.
//!
//! Everything here is:
//! - **pure** — a function of its inputs (no globals, no `Instant::now()`); all
//!   animation is driven by an injected `phase`/`t` so snapshots are stable (the
//!   determinism LAW). A test feeds a fixed clock and the picture is reproducible.
//! - **L0-only** — emits [`QuadInstance`]/[`LineInstance`]/[`CircleInstance`]/
//!   [`RingInstance`], the same vocabulary the CPU raster + GPU pipeline both draw,
//!   so the effects work on the always-available CPU lane (`l1-vello` is an
//!   *elevation*, never a requirement).
//! - **domain-agnostic** — it knows nothing about "Person" or "Debt"; a caller
//!   decides which nodes glow, which edges flow, where a shockwave fires.
//!
//! ## The helper menu (maps onto the aesthetic spec)
//! - [`glow_halo`] — a soft colored light-bleed ring behind a node (the glossy
//!   orb look). The CPU bloom substitute for an L1 gaussian glow.
//! - [`ao_shadow`] — a toon drop-shadow / ambient-occlusion disc under a node
//!   (deeper where nodes bunch — clustered nodes pool a darker shadow).
//! - [`dash_line`] — an **animated dash-array** stroke (a `→` flow of segments that
//!   marches along the edge as `phase` advances) — debt flowing toward enforcement.
//! - [`particles_on_edge`] — light-tracer **particles** zipping along an edge
//!   (money moving Loan→Person), positions a pure function of `phase`.
//! - [`pulse`] / [`strobe`] — deterministic 0..1 envelopes for the Debt **pulse**
//!   and PoliceRecord **strobe** (animation timing, injected-clock driven).
//! - [`shockwave_ring`] — a radial ring expanding from a clicked node.
//! - [`bloom_composite`] — a cheap separable box-blur **bloom** post-pass over a
//!   straight-RGBA8 [`Frame`]: bright pixels bleed light into their neighbours so
//!   intersecting neon lines mix into colored "explosions".
//! - [`lerp_rgba`] / [`gradient_by_scalar`] — a 2-stop (or multi-stop) colour ramp
//!   keyed by a scalar in `[0,1]` (the gradient-fill-by-scalar engine primitive).

use super::Frame;
use super::prim::{CircleInstance, LineInstance, QuadInstance, RingInstance, shape};

/// τ (one full animation cycle) — phases are in **cycles** (`0.0..1.0` is one loop),
/// so a caller advances `phase += dt / period` and the look is period-independent.
const TAU: f32 = std::f32::consts::TAU;

// ───────────────────────────────────────────────────────────────────────────
// Colour ramps (gradient-by-scalar engine primitive)
// ───────────────────────────────────────────────────────────────────────────

/// Linear-interpolate two straight RGBA colours at `t ∈ [0,1]`.
#[inline]
pub fn lerp_rgba(a: [f32; 4], b: [f32; 4], t: f32) -> [f32; 4] {
    let t = t.clamp(0.0, 1.0);
    [
        a[0] + (b[0] - a[0]) * t,
        a[1] + (b[1] - a[1]) * t,
        a[2] + (b[2] - a[2]) * t,
        a[3] + (b[3] - a[3]) * t,
    ]
}

/// Sample a piecewise-linear **multi-stop** gradient (`stops` sorted by position)
/// at `t ∈ [0,1]` — the domain-agnostic "fill-by-scalar" ramp (debt-heat, degree,
/// population). Clamps below the first / above the last stop. `stops` must be
/// non-empty.
pub fn gradient_by_scalar(stops: &[(f32, [f32; 4])], t: f32) -> [f32; 4] {
    debug_assert!(!stops.is_empty(), "gradient needs at least one stop");
    let t = t.clamp(0.0, 1.0);
    if t <= stops[0].0 {
        return stops[0].1;
    }
    for w in stops.windows(2) {
        let (p0, c0) = w[0];
        let (p1, c1) = w[1];
        if t <= p1 {
            let span = (p1 - p0).max(1e-6);
            return lerp_rgba(c0, c1, (t - p0) / span);
        }
    }
    stops[stops.len() - 1].1
}

// ───────────────────────────────────────────────────────────────────────────
// Animation envelopes (injected-clock driven, pure)
// ───────────────────────────────────────────────────────────────────────────

/// A smooth `0..1` **pulse** envelope (a raised cosine) at `phase` cycles —
/// `0 → 1 → 0` once per cycle. The Debt/KfmCase "intense glow" breathing.
#[inline]
pub fn pulse(phase: f32) -> f32 {
    0.5 - 0.5 * (phase * TAU).cos()
}

/// A hard **strobe** envelope at `phase` cycles with duty `duty ∈ (0,1)` — `1.0`
/// for the first `duty` of each cycle, else `0.0` (PoliceRecord hazard flash). A
/// pure step so snapshots at a fixed `phase` are exact.
#[inline]
pub fn strobe(phase: f32, duty: f32) -> f32 {
    if phase.rem_euclid(1.0) < duty.clamp(0.0, 1.0) { 1.0 } else { 0.0 }
}

// ───────────────────────────────────────────────────────────────────────────
// Node beauty: glow halo + ambient-occlusion drop-shadow
// ───────────────────────────────────────────────────────────────────────────

/// A soft colored **glow halo** ring behind a node marker — the CPU light-bleed
/// that makes a node read as a glossy orb. `r` is the marker radius, `intensity`
/// the halo alpha (`0..1`), `spread` the outer-radius multiplier (≥ 1).
#[inline]
pub fn glow_halo(center: [f32; 2], r: f32, color: [f32; 3], intensity: f32, spread: f32) -> RingInstance {
    let spread = spread.max(1.05);
    RingInstance {
        center,
        radius: r * spread,
        inner: r * 1.05,
        color: [color[0], color[1], color[2], intensity.clamp(0.0, 1.0)],
        aa: r * 0.5 + 1.5, // a wide AA band = a soft, blurry bleed (no GPU blur needed)
    }
}

/// A toon **ambient-occlusion drop-shadow** disc under a node — a dark, soft circle
/// offset down-right, so clustered nodes pool a deeper shadow (the "ray-traced"
/// grounding). `r` the marker radius, `depth` the shadow alpha (`0..1`).
#[inline]
pub fn ao_shadow(center: [f32; 2], r: f32, depth: f32) -> CircleInstance {
    CircleInstance {
        center: [center[0] + r * 0.22, center[1] + r * 0.30],
        radius: r * 1.18,
        color: [0.0, 0.0, 0.0, depth.clamp(0.0, 1.0)],
        aa: r * 0.6 + 1.5,
    }
}

/// Build glow + AO for a batch of node markers in one pass (the common case): pull
/// the SQUARE/CIRCLE/DIAMOND node quads out of `quads`, and for each emit an AO
/// shadow (under) + a glow halo (also under, over the shadow). Returns
/// `(ao_quads, glow_quads)` already lowered, so a caller pushes
/// `shadows → glows → original quads` for the layered orb look. `intensity` scales
/// the glow alpha; `ao` the shadow alpha.
pub fn node_decor(
    quads: &[QuadInstance],
    intensity: f32,
    ao: f32,
) -> (Vec<QuadInstance>, Vec<QuadInstance>) {
    let mut shadows = Vec::with_capacity(quads.len());
    let mut glows = Vec::with_capacity(quads.len());
    for q in quads {
        if q.shape == shape::SQUARE || q.shape == shape::CIRCLE || q.shape == shape::DIAMOND {
            let r = q.radius;
            shadows.push(ao_shadow(q.center, r, ao).lower());
            glows.push(glow_halo(q.center, r, [q.color[0], q.color[1], q.color[2]], intensity, 2.1).lower());
        }
    }
    (shadows, glows)
}

// ───────────────────────────────────────────────────────────────────────────
// Edge beauty: animated dash-array + particle tracers
// ───────────────────────────────────────────────────────────────────────────

/// An **animated dash-array** line `a → b`: the segment is chopped into `dash`-long
/// lit pieces separated by `gap`, and the whole pattern **marches** along the
/// direction by `phase` (in dash+gap units) — a directional "flow". Pure in
/// `phase`, so a fixed clock gives a fixed picture. `half_width`/`aa`/`color` as
/// for a [`LineInstance`].
#[allow(clippy::too_many_arguments)] // public signature hosts call: kept as is
pub fn dash_line(
    a: [f32; 2],
    b: [f32; 2],
    half_width: f32,
    aa: f32,
    color: [f32; 4],
    dash: f32,
    gap: f32,
    phase: f32,
) -> Vec<LineInstance> {
    let dash = dash.max(0.5);
    let gap = gap.max(0.0);
    let period = dash + gap;
    let dx = b[0] - a[0];
    let dy = b[1] - a[1];
    let len = (dx * dx + dy * dy).sqrt();
    if len < 1e-3 {
        return Vec::new();
    }
    let (ux, uy) = (dx / len, dy / len);
    // March offset (always backward against the flow so dashes appear to move a→b).
    let mut t = -(phase.rem_euclid(1.0) * period);
    let mut out = Vec::new();
    while t < len {
        let s = t.max(0.0);
        let e = (t + dash).min(len);
        if e > s {
            out.push(LineInstance::round(
                [a[0] + ux * s, a[1] + uy * s],
                [a[0] + ux * e, a[1] + uy * e],
                half_width,
                aa,
                color,
            ));
        }
        t += period;
    }
    out
}

/// **Light-tracer particles** zipping along an edge `a → b`: `n` evenly-spaced
/// discs whose fractional position is `(i/n + phase) mod 1`, so they flow a→b as
/// `phase` advances. Pure in `phase`. `radius`/`color` per particle.
pub fn particles_on_edge(
    a: [f32; 2],
    b: [f32; 2],
    n: usize,
    radius: f32,
    color: [f32; 4],
    phase: f32,
) -> Vec<CircleInstance> {
    if n == 0 {
        return Vec::new();
    }
    (0..n)
        .map(|i| {
            let f = ((i as f32 / n as f32) + phase).rem_euclid(1.0);
            // Brighten toward the head of the trail (a fading comet look).
            let head = 0.55 + 0.45 * f; // dim at the tail, bright at the front
            let c = [color[0], color[1], color[2], (color[3] * head).clamp(0.0, 1.0)];
            CircleInstance {
                center: [a[0] + (b[0] - a[0]) * f, a[1] + (b[1] - a[1]) * f],
                radius: radius * (0.6 + 0.6 * f),
                color: c,
                aa: 1.0,
            }
        })
        .collect()
}

// ───────────────────────────────────────────────────────────────────────────
// Interaction: shockwave
// ───────────────────────────────────────────────────────────────────────────

/// A radial **shockwave** ring expanding from `center` as `t ∈ [0,1]` runs
/// (0 = just fired, 1 = faded out): the ring grows `r0 → r0 + reach` while its
/// alpha fades `1 → 0`. Pure in `t`. The neon-dashboard "click ripple".
#[inline]
pub fn shockwave_ring(center: [f32; 2], r0: f32, reach: f32, color: [f32; 3], t: f32) -> RingInstance {
    let t = t.clamp(0.0, 1.0);
    let radius = r0 + reach * t;
    let thickness = (reach * 0.10).max(2.0);
    RingInstance {
        center,
        radius,
        inner: (radius - thickness).max(0.0),
        color: [color[0], color[1], color[2], (1.0 - t).powf(1.4)],
        aa: 2.0,
    }
}

// ───────────────────────────────────────────────────────────────────────────
// Bloom (CPU post-process)
// ───────────────────────────────────────────────────────────────────────────

/// A cheap separable **bloom** post-pass over a straight-RGBA8 [`Frame`]: extract
/// the pixels brighter than `threshold` (`0..1` luma), blur them with a small
/// box-blur of `radius` px (separable, two passes), and **add** that light back
/// onto the frame scaled by `intensity`. Intersecting neon lines therefore bleed
/// and mix into colored "explosions" — the spec's bloom, with no GPU.
///
/// Pure, in-place, deterministic. `radius` is clamped to a small range so a wasm
/// frame stays snappy. A no-op when `intensity <= 0` or `radius == 0`.
pub fn bloom_composite(frame: &mut Frame, threshold: f32, radius: u32, intensity: f32) {
    if intensity <= 0.0 || radius == 0 || frame.width == 0 || frame.height == 0 {
        return;
    }
    let (w, h) = (frame.width as usize, frame.height as usize);
    let radius = radius.min(8) as i32; // keep the blur cheap (wasm-safe)
    let n = w * h;

    // 1) Bright-pass: keep only pixels whose luma exceeds the threshold.
    let mut bright = vec![0f32; n * 3];
    for (i, px) in frame.rgba.as_chunks::<4>().0.iter().enumerate() {
        let r = px[0] as f32 / 255.0;
        let g = px[1] as f32 / 255.0;
        let b = px[2] as f32 / 255.0;
        let luma = 0.2126 * r + 0.7152 * g + 0.0722 * b;
        if luma > threshold {
            // soft knee so the bloom ramps in rather than hard-clips
            let k = ((luma - threshold) / (1.0 - threshold).max(1e-3)).clamp(0.0, 1.0);
            bright[i * 3] = r * k;
            bright[i * 3 + 1] = g * k;
            bright[i * 3 + 2] = b * k;
        }
    }

    // 2) Separable box-blur (horizontal then vertical) of the bright layer.
    let win = (2 * radius + 1) as f32;
    let mut tmp = vec![0f32; n * 3];
    // horizontal
    for y in 0..h {
        for x in 0..w {
            let mut acc = [0f32; 3];
            for d in -radius..=radius {
                let sx = (x as i32 + d).clamp(0, w as i32 - 1) as usize;
                let si = (y * w + sx) * 3;
                acc[0] += bright[si];
                acc[1] += bright[si + 1];
                acc[2] += bright[si + 2];
            }
            let di = (y * w + x) * 3;
            tmp[di] = acc[0] / win;
            tmp[di + 1] = acc[1] / win;
            tmp[di + 2] = acc[2] / win;
        }
    }
    // vertical (back into `bright`)
    for y in 0..h {
        for x in 0..w {
            let mut acc = [0f32; 3];
            for d in -radius..=radius {
                let sy = (y as i32 + d).clamp(0, h as i32 - 1) as usize;
                let si = (sy * w + x) * 3;
                acc[0] += tmp[si];
                acc[1] += tmp[si + 1];
                acc[2] += tmp[si + 2];
            }
            let di = (y * w + x) * 3;
            bright[di] = acc[0] / win;
            bright[di + 1] = acc[1] / win;
            bright[di + 2] = acc[2] / win;
        }
    }

    // 3) Additive composite the blurred light back onto the frame.
    for (i, px) in frame.rgba.as_chunks_mut::<4>().0.iter_mut().enumerate() {
        for k in 0..3 {
            let base = px[k] as f32 / 255.0;
            let add = bright[i * 3 + k] * intensity;
            px[k] = ((base + add) * 255.0).round().clamp(0.0, 255.0) as u8;
        }
        // bloom never makes a transparent pixel opaque on its own, but it lifts
        // alpha where it added real light so the glow is visible over the ground.
        if px[3] == 0 {
            let lit = bright[i * 3] + bright[i * 3 + 1] + bright[i * 3 + 2];
            if lit * intensity > 0.02 {
                px[3] = (lit * intensity * 255.0).round().clamp(0.0, 255.0) as u8;
            }
        }
    }
}

// ───────────────────────────────────────────────────────────────────────────
// The GLOW STROKE ladder — an EverQuest-II-style luminous line, on any renderer
// ───────────────────────────────────────────────────────────────────────────

/// **One pass of a layered glow stroke.** A glowing line is not one stroke, it is a
/// LADDER of them drawn widest-first over the same path: a wide, nearly transparent
/// bleed, a mid halo, and a thin core that is blended toward white so the line reads
/// as *hot* rather than merely coloured.
///
/// Every field is a MULTIPLIER or a fraction, never a pixel count, so the same ladder
/// serves a 1.5 px graph edge and a 7 m map ribbon.
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct GlowPass {
    /// Stroke width as a multiple of the caller's core width.
    pub width_mul: f32,
    /// Alpha of this pass, `0..1`.
    pub alpha: f32,
    /// How far the ink is blended toward white, `0..1` — `0` keeps the hue, `1` is
    /// pure white. Only the innermost passes carry any; that is the whole "hot core".
    pub white: f32,
}

/// **The ladder** — five passes, widest and faintest first, ending on a near-white
/// core. Read once, projected by every renderer (LAW: one writer).
///
/// # Why five and why these numbers
///
/// The three-pass ladder korp shipped before this — `(9.0, α46) (4.5, α120)
/// (1.6, α255)` at the hue's own colour — did not read as a glow, and the reasons are
/// measurable, not aesthetic:
///
/// * **The widest pass was too narrow.** A halo has to be several times the core to
///   read as light leaving the line; at 5.6× core with α 0.18 it read as a second,
///   thicker line. Here the outermost pass is 14× the core at α 0.09.
/// * **The core kept the hue.** A saturated cyan at α 1.0 is a cyan line. Light is
///   white at the centre and coloured at the edge — that is what a bloom does, and
///   what an eye reads as emission. The inner two passes carry `white` 0.55 / 0.9.
/// * **The alpha budget was linear.** Stacked translucent strokes composite
///   multiplicatively, so a linear ramp piles most of the ink in the middle. The
///   ladder is geometric: 0.09 → 0.16 → 0.30 → 0.62 → 1.0.
pub const GLOW_LADDER: [GlowPass; 5] = [
    GlowPass { width_mul: 14.0, alpha: 0.09, white: 0.0 },
    GlowPass { width_mul: 8.0, alpha: 0.16, white: 0.0 },
    GlowPass { width_mul: 4.2, alpha: 0.30, white: 0.10 },
    GlowPass { width_mul: 2.0, alpha: 0.62, white: 0.55 },
    GlowPass { width_mul: 1.0, alpha: 1.0, white: 0.90 },
];

/// **The ladder lowered to concrete `(width, rgba)` strokes** for one core width and
/// one ink. Widest/faintest first — a caller draws them IN ORDER over the same path.
///
/// `ink` is straight (non-premultiplied) linear RGB in `0..1`. The returned alpha is
/// `pass.alpha`, so a caller that also carries an opacity multiplies it in.
///
/// Pure and deterministic: same inputs, same ladder, on CPU and GPU alike.
#[must_use]
pub fn glow_stroke_passes(core_width: f32, ink: [f32; 3]) -> Vec<(f32, [f32; 4])> {
    glow_stroke_passes_on(core_width, ink, GlowGround::Dark)
}

/// **What the glow is drawn ON.** A luminous line is a contrast effect, and the two
/// grounds need opposite cores — so this is a required input, not a style option.
///
/// MEASURED 2026-09-03 (korp's `tests/golden_trail_pixels.rs`, the same ladder on both
/// papers): over the dark pane the white-hot core reads as emission and the frame is a
/// neon filament. Over the cartographic DAY paper (`#F2EFE9`, which is the pane the owner
/// was actually looking at) the identical ladder composites to `(232, 250, 253)` — a
/// near-white line on near-white paper, i.e. **invisible** — and the low-alpha halo
/// desaturates to grey. The picture was a grey smudge with a hole down the middle.
///
/// Over light paper a glowing line is the *highlighter* look instead: the core is the
/// hue at full saturation and DARKENED, the halo is the hue at higher alpha than the
/// dark-ground ladder needs. Same widths, same reach, same ordering — only the tone
/// flips.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum GlowGround {
    /// A dark pane: the core burns toward white.
    Dark,
    /// Light paper: the core deepens toward the saturated hue.
    Light,
}

/// **How far EVERY light-ground pass is pushed toward black** — the halo included.
///
/// A low-alpha saturated hue over cream composites to a pale wash, and a pale wash on
/// pale paper is grey: the first light-ground attempt (halo at the pure hue, core
/// deepened) drew a grey smudge with a blue thread in it. Deepening the whole ladder
/// turns the halo into a coloured **contact shadow** — which is what makes a bright line
/// read as luminous against a bright ground, in EQ2 and on paper alike.
const GLOW_LIGHT_DEEPEN_BASE: f32 = 0.30;
/// …and how much FURTHER the core is deepened, on top of the base — so the ladder still
/// has a hot centre, just a saturated one instead of a white one.
const GLOW_LIGHT_DEEPEN_CORE: f32 = 0.30;
/// Alpha multiplier for the light-ground ladder — a wash that reads on a dark pane is
/// nothing at all on cream.
const GLOW_LIGHT_ALPHA_GAIN: f32 = 2.2;

/// **The ladder lowered to concrete `(width, rgba)` strokes** for one core width, one
/// ink and the ground it is drawn on. Widest/faintest first — a caller draws them IN
/// ORDER over the same path.
///
/// `ink` is straight (non-premultiplied) RGB in `0..1`. The returned alpha is the
/// pass's, so a caller carrying its own opacity multiplies it in.
///
/// Pure and deterministic: same inputs, same ladder, on CPU and GPU alike.
#[must_use]
pub fn glow_stroke_passes_on(
    core_width: f32,
    ink: [f32; 3],
    ground: GlowGround,
) -> Vec<(f32, [f32; 4])> {
    let core = core_width.max(0.1);
    GLOW_LADDER
        .iter()
        .map(|p| {
            let t = p.white.clamp(0.0, 1.0);
            let (rgb, alpha) = match ground {
                // Toward WHITE by `white`: a hot centre inside a coloured bleed.
                GlowGround::Dark => (
                    [
                        ink[0] + (1.0 - ink[0]) * t,
                        ink[1] + (1.0 - ink[1]) * t,
                        ink[2] + (1.0 - ink[2]) * t,
                    ],
                    p.alpha,
                ),
                // Toward BLACK by `white · GLOW_LIGHT_DEEPEN`, and every pass carries
                // more ink: the same shape, inverted for paper.
                GlowGround::Light => {
                    let k = 1.0 - GLOW_LIGHT_DEEPEN_BASE - t * GLOW_LIGHT_DEEPEN_CORE;
                    (
                        [ink[0] * k, ink[1] * k, ink[2] * k],
                        p.alpha * GLOW_LIGHT_ALPHA_GAIN,
                    )
                }
            };
            (core * p.width_mul, [rgb[0], rgb[1], rgb[2], alpha.clamp(0.0, 1.0)])
        })
        .collect()
}

/// **The glow as a CROSS-SECTION — one ribbon, not a stack of strokes.**
///
/// Returns `(half-offset px from the centreline, straight rgba)` from the OUTER edge
/// inward to the centre, for a caller that builds a per-vertex-coloured mesh.
///
/// # Why this exists (owner, 2026-09-03)
///
/// *"the golden path is looking like shit, its not a soft spline its a flat band with
/// some smoth edges. the eqII paths where like a soul / spirit trace shiny and
/// transparent glowing"*
///
/// [`glow_stroke_passes_on`] hands back five concentric STROKES, and every renderer
/// drew them source-over on top of each other. The arithmetic is what he was looking
/// at: composite alpha at the centreline is `1 − Π(1 − αᵢ)`, and the ladder's core pass
/// is `alpha 1.0`, so the middle of the trail is **fully opaque** and only the outermost
/// halo is soft. That is a flat band with smooth edges — paint, not light. Nothing
/// shows through it, which is the opposite of a spirit trace.
///
/// The numbers were never wrong; the way they were APPLIED was. Read the same ladder as
/// a profile across the width and interpolate between the rings in ONE mesh and you get
/// a true falloff: bright at the centreline, zero at the edge, the map visible through
/// the whole thing, and no plateau anywhere because nothing is drawn twice.
///
/// So this is the same `GLOW_LADDER` — the one writer of what a glow is — projected on
/// a different axis. A width multiple becomes an OFFSET and an alpha becomes a VERTEX
/// alpha. The outermost ring is forced to `alpha 0` so the ribbon fades into the ground
/// instead of ending on an edge, which is the other half of "smooth edges": an
/// antialiased boundary is still a boundary.
#[must_use]
pub fn glow_cross_section(core_width: f32, ink: [f32; 3], ground: GlowGround) -> Vec<(f32, [f32; 4])> {
    let passes = glow_stroke_passes_on(core_width, ink, ground);
    let mut out: Vec<(f32, [f32; 4])> = Vec::with_capacity(passes.len() + 1);
    // The widest pass defines the ribbon's edge, and the edge is TRANSPARENT.
    if let Some((w, c)) = passes.first() {
        out.push((w * 0.5, [c[0], c[1], c[2], 0.0]));
    }

    // ── The ACCUMULATION, which is the whole difference between one ribbon and five
    //    stacked strokes ──────────────────────────────────────────────────────────
    //
    // The ladder used to be painted as five separate translucent strokes on top of one
    // another, so at any distance from the centre the eye saw every pass at least that
    // wide, composited. The core was bright because five alphas had accumulated there,
    // not because the innermost pass was strong.
    //
    // A ribbon is ONE draw. Handing each ring its own pass' alpha therefore throws the
    // accumulation away, and the trail comes out far too faint to read — MEASURED by
    // `golden_trail_pixels::the_glow_ladder_beats_the_three_pass_line`, which caught the
    // first version of this function at a core departing the paper by **56** where the
    // stacked ladder reached **204**. That is a trail you cannot see on a map, which is
    // the same complaint the ribbon was built to answer, arrived at from the other side.
    //
    // So each ring carries the OVER-composite of every pass from the outermost down to
    // itself, and the centreline carries all of them — the same arithmetic
    // `glow_core_coverage` reports as one number, done per ring and in colour.
    let mut acc: [f32; 4] = [0.0, 0.0, 0.0, 0.0];
    for (w, c) in &passes {
        acc = over(*c, acc);
        out.push((w * 0.5, acc));
    }
    // …and the centreline itself, at the fully accumulated colour: the innermost pass is
    // a stroke of finite width, so without this the profile would have a flat top exactly
    // as wide as the core. A ribbon wants a POINT of maximum, not a plateau — that
    // plateau is the defect this function exists to remove, in miniature.
    out.push((0.0, acc));
    out
}

/// `src` over `dst`, both premultiplied-by-nothing straight RGBA — the Porter-Duff
/// operator the stacked ladder performed implicitly by drawing one pass after another.
/// Returns straight RGBA again so the mesh can hand it to a vertex.
fn over(src: [f32; 4], dst: [f32; 4]) -> [f32; 4] {
    let (sa, da) = (src[3].clamp(0.0, 1.0), dst[3].clamp(0.0, 1.0));
    let out_a = sa + da * (1.0 - sa);
    if out_a <= f32::EPSILON {
        return [src[0], src[1], src[2], 0.0];
    }
    let mix = |s: f32, d: f32| (s * sa + d * da * (1.0 - sa)) / out_a;
    [
        mix(src[0], dst[0]),
        mix(src[1], dst[1]),
        mix(src[2], dst[2]),
        out_a,
    ]
}

/// **The ink coverage a whole ladder lays down at the line's centre**, `0..1` — the
/// over-operator composite of every pass' alpha. The single number "how bright is the
/// core", so a change to [`GLOW_LADDER`] that quietly dims the line is visible as a
/// number and not only as a picture.
#[must_use]
pub fn glow_core_coverage() -> f32 {
    GLOW_LADDER.iter().fold(0.0, |acc, p| acc + p.alpha.clamp(0.0, 1.0) * (1.0 - acc))
}

/// **How wide the glow reaches**, as a multiple of the core width — the outermost
/// pass. The halo's read is this number; a ladder whose widest pass is ~2× core is a
/// thick line, not a glow.
#[must_use]
pub fn glow_reach_mul() -> f32 {
    GLOW_LADDER.iter().fold(0.0f32, |m, p| m.max(p.width_mul))
}

/// **The flow phase along a path**, `0..1` — where the light-tracer particles sit at
/// clock `t` seconds for a stroke that cycles every `period_s`. Pure in `t` (the
/// determinism LAW); pair it with [`particles_on_edge`] to make a glow stroke *move*.
#[must_use]
pub fn glow_flow_phase(t: f32, period_s: f32) -> f32 {
    (t / period_s.max(1e-3)).rem_euclid(1.0)
}

#[cfg(test)]
mod tests {
    use super::*;

    /// INJECT-ASSERT: the 2-stop / multi-stop ramp lands on the right colours at
    /// the ends and blends in the middle (the gradient-by-scalar primitive).
    #[test]
    fn gradient_by_scalar_ramps_and_clamps() {
        let stops = [(0.0, [0.0, 0.0, 1.0, 1.0]), (1.0, [1.0, 0.0, 0.0, 1.0])];
        assert_eq!(gradient_by_scalar(&stops, -1.0), stops[0].1, "clamps below");
        assert_eq!(gradient_by_scalar(&stops, 2.0), stops[1].1, "clamps above");
        let mid = gradient_by_scalar(&stops, 0.5);
        assert!((mid[0] - 0.5).abs() < 1e-5 && (mid[2] - 0.5).abs() < 1e-5, "mid blends: {mid:?}");
        // A three-stop ramp picks the right segment.
        let three = [(0.0, [0.0; 4]), (0.5, [1.0, 1.0, 1.0, 1.0]), (1.0, [0.0; 4])];
        assert!(gradient_by_scalar(&three, 0.25)[0] > 0.4, "rises to the mid stop");
        assert!(gradient_by_scalar(&three, 0.75)[0] < 0.6, "falls past the mid stop");
    }

    /// INJECT-ASSERT: pulse/strobe are deterministic envelopes — the SAME phase
    /// gives the SAME value (snapshot-stable), and they actually move.
    #[test]
    fn pulse_and_strobe_are_deterministic_envelopes() {
        assert!(pulse(0.0).abs() < 1e-5, "pulse troughs at phase 0");
        assert!((pulse(0.5) - 1.0).abs() < 1e-5, "pulse peaks at half-cycle");
        assert_eq!(pulse(0.25), pulse(0.25), "deterministic");
        assert_eq!(strobe(0.05, 0.5), 1.0, "strobe lit in the duty window");
        assert_eq!(strobe(0.75, 0.5), 0.0, "strobe dark past the duty window");
        assert_eq!(strobe(1.05, 0.5), 1.0, "strobe is periodic (phase wraps)");
    }

    /// INJECT-ASSERT: the animated dash marches — at a different phase the lit
    /// segments sit at different offsets (a real flow, not a static dash).
    #[test]
    fn dash_line_marches_with_phase() {
        let a = [0.0, 0.0];
        let b = [100.0, 0.0];
        let d0 = dash_line(a, b, 2.0, 1.0, [1.0; 4], 8.0, 6.0, 0.0);
        let d1 = dash_line(a, b, 2.0, 1.0, [1.0; 4], 8.0, 6.0, 0.5);
        assert!(!d0.is_empty() && !d1.is_empty(), "the dash produced segments");
        // The pattern marches: the first lit segment ENDS at a different offset
        // (its start may clamp to 0 at both phases, but the lit length shifts).
        assert_ne!(d0[0].b[0], d1[0].b[0], "dashes moved along the edge with phase");
        // Determinism: same phase, same geometry.
        let d0b = dash_line(a, b, 2.0, 1.0, [1.0; 4], 8.0, 6.0, 0.0);
        assert_eq!(d0[0].a, d0b[0].a, "same phase → same dash (start)");
        assert_eq!(d0[0].b, d0b[0].b, "same phase → same dash (end)");
    }

    /// INJECT-ASSERT: particles ride the edge — at phase 0 they sit at i/n, and a
    /// phase bump slides every particle along the segment by the same fraction.
    #[test]
    fn particles_flow_along_the_edge() {
        let a = [0.0, 0.0];
        let b = [200.0, 0.0];
        let p0 = particles_on_edge(a, b, 4, 3.0, [1.0; 4], 0.0);
        let p1 = particles_on_edge(a, b, 4, 3.0, [1.0; 4], 0.25);
        assert_eq!(p0.len(), 4);
        // The first particle starts at the tail and advances a quarter-edge.
        assert!((p0[0].center[0] - 0.0).abs() < 1e-3, "particle 0 at the tail at phase 0");
        assert!((p1[0].center[0] - 50.0).abs() < 1e-3, "particle 0 advanced to x=50 at phase 0.25");
    }

    /// INJECT-ASSERT: the shockwave grows + fades with t (a real ripple), staying
    /// a valid annulus.
    #[test]
    fn shockwave_expands_and_fades() {
        let early = shockwave_ring([50.0, 50.0], 10.0, 100.0, [1.0, 0.4, 0.9], 0.1);
        let late = shockwave_ring([50.0, 50.0], 10.0, 100.0, [1.0, 0.4, 0.9], 0.9);
        assert!(late.radius > early.radius, "the ring expands with t");
        assert!(late.color[3] < early.color[3], "and fades out");
        assert!(early.inner < early.radius, "valid annulus");
    }

    /// INJECT-ASSERT: node_decor emits a shadow + a glow under each node marker
    /// (one of each per drawable quad), AND the glow carries the node's colour.
    #[test]
    fn node_decor_emits_shadow_and_glow_per_node() {
        let q = QuadInstance {
            center: [40.0, 40.0],
            radius: 8.0,
            inner: 2.0,
            color: [0.2, 0.8, 1.0, 1.0],
            aa: 1.0,
            shape: shape::SQUARE,
            _pad: [0.0, 0.0],
        };
        let (shadows, glows) = node_decor(&[q], 0.5, 0.4);
        assert_eq!(shadows.len(), 1, "one AO shadow under the node");
        assert_eq!(glows.len(), 1, "one glow halo behind the node");
        // The glow is the node's hue at the requested intensity; the shadow is dark.
        assert!((glows[0].color[2] - 1.0).abs() < 1e-5, "glow carries the node blue");
        assert!((glows[0].color[3] - 0.5).abs() < 1e-5, "glow at the requested intensity");
        assert!(shadows[0].color[0] < 0.05, "shadow is black");
        assert!(glows[0].radius > q.radius, "glow is larger than the marker (a bleed)");
    }

    /// INJECT-ASSERT: bloom actually spreads light — a single bright pixel on a
    /// dark frame lights up its neighbours after the pass (and the source stays
    /// lit), proving the box-blur bleed ran (not "didn't panic").
    #[test]
    fn bloom_spreads_light_to_neighbours() {
        let (w, h) = (9u32, 9u32);
        let mut rgba = vec![0u8; (w * h * 4) as usize];
        // One opaque white pixel dead centre on a transparent black ground.
        let c = ((4 * w + 4) * 4) as usize;
        rgba[c..c + 4].copy_from_slice(&[255, 255, 255, 255]);
        let mut frame = Frame { width: w, height: h, rgba };

        let neighbour = ((4 * w + 5) * 4) as usize; // one px to the right
        assert_eq!(frame.rgba[neighbour], 0, "neighbour starts dark");
        bloom_composite(&mut frame, 0.5, 2, 1.0);
        assert!(frame.rgba[neighbour] > 0, "bloom bled light onto the neighbour");
        assert!(frame.rgba[neighbour + 3] > 0, "and lifted its alpha so the glow shows");
        // The original bright pixel stays lit.
        assert!(frame.rgba[c] > 200, "the source pixel stays bright");
    }

    /// INJECT-ASSERT: bloom is a no-op when disabled (intensity 0 / radius 0) — the
    /// frame is byte-identical, so toggling bloom off truly removes it.
    #[test]
    fn bloom_disabled_is_a_noop() {
        let (w, h) = (5u32, 5u32);
        let mut rgba = vec![0u8; (w * h * 4) as usize];
        rgba[((2 * w + 2) * 4) as usize..((2 * w + 2) * 4) as usize + 4]
            .copy_from_slice(&[255, 255, 255, 255]);
        let before = rgba.clone();
        let mut frame = Frame { width: w, height: h, rgba };
        bloom_composite(&mut frame, 0.5, 0, 1.0);
        assert_eq!(frame.rgba, before, "radius 0 → no-op");
        bloom_composite(&mut frame, 0.5, 2, 0.0);
        assert_eq!(frame.rgba, before, "intensity 0 → no-op");
    }

    // ── the GLOW STROKE ladder ────────────────────────────────────────────

    /// The ladder that shipped in korp before this lane — the one whose pixels
    /// The owner said were "not glowing souline like in everquest-II yet". Widths in
    /// px over a 1.6 px core, alphas 0..1. Used ONLY as this module's red control.
    fn the_old_three_pass_ladder() -> Vec<(f32, [f32; 4])> {
        let ink = [0.0, 0.95, 1.0];
        [(9.0f32, 46.0f32), (4.5, 120.0), (1.6, 255.0)]
            .iter()
            .map(|&(w, a)| (w, [ink[0], ink[1], ink[2], a / 255.0]))
            .collect()
    }

    /// **RED FIRST — the old ladder fails every gate the new one passes.** Reach,
    /// hot core and coverage are each measured on the LOWERED strokes, so a ladder
    /// edit that quietly dims the line fails here rather than in a screenshot.
    #[test]
    fn the_old_three_pass_ladder_is_not_a_glow() {
        let old = the_old_three_pass_ladder();
        let core_w = 1.6f32;
        let reach = old.iter().fold(0.0f32, |m, &(w, _)| m.max(w)) / core_w;
        assert!(reach < 6.0, "the old halo reached only {reach:.1}x the core — a thick line");
        // Its core keeps the hue: the red channel never lifts off the ink's 0.0.
        let core = old.last().expect("three passes").1;
        assert!(core[0] < 0.2, "the old core is saturated cyan (r={}), not hot white", core[0]);
        // And its coverage is dominated by one opaque pass rather than a ramp.
        let alphas: Vec<f32> = old.iter().map(|p| p.1[3]).collect();
        assert!(alphas[0] > 0.15, "the old outer pass was too opaque to read as bleed: {}", alphas[0]);
    }

    /// **The new ladder IS a glow** — wide bleed, geometric alpha ramp, white-hot core.
    #[test]
    fn the_glow_ladder_reaches_wide_and_burns_white_at_the_core() {
        let ink = [0.0, 0.95, 1.0];
        let passes = glow_stroke_passes(1.6, ink);
        assert_eq!(passes.len(), GLOW_LADDER.len());

        // 1. WIDTH: widest first, and the halo reaches far past the core.
        let widths: Vec<f32> = passes.iter().map(|p| p.0).collect();
        for w in widths.windows(2) {
            assert!(w[0] > w[1], "the ladder is drawn widest-first: {widths:?}");
        }
        assert!((widths[widths.len() - 1] - 1.6).abs() < 1e-4, "the last pass IS the core width");
        assert!(glow_reach_mul() >= 10.0, "the halo reaches {}x the core", glow_reach_mul());

        // 2. ALPHA: a monotone geometric ramp, faint outside, opaque at the core.
        let alphas: Vec<f32> = passes.iter().map(|p| p.1[3]).collect();
        for a in alphas.windows(2) {
            assert!(a[1] > a[0], "alpha rises inward: {alphas:?}");
        }
        assert!(alphas[0] <= 0.10, "the outer bleed is nearly transparent: {}", alphas[0]);
        assert!(alphas[alphas.len() - 1] >= 0.99, "the core is opaque: {:?}", alphas.last());
        // geometric, not linear: each step is a bigger jump than the last.
        let steps: Vec<f32> = alphas.windows(2).map(|w| w[1] - w[0]).collect();
        for s in steps.windows(2) {
            assert!(s[1] > s[0], "the alpha ramp accelerates inward: {steps:?}");
        }

        // 3. COLOUR: the outer passes keep the hue, the core burns toward white.
        let outer = passes[0].1;
        assert!((outer[0] - ink[0]).abs() < 1e-6, "the bleed is the pure hue");
        let core = passes[passes.len() - 1].1;
        assert!(core[0] > 0.85, "the core is white-hot: r={}", core[0]);
        assert!(core[2] > 0.95, "…and still carries the hue's blue: b={}", core[2]);

        // 4. COVERAGE: the stacked passes actually reach opacity at the centre.
        let cov = glow_core_coverage();
        assert!(cov > 0.99, "the ladder covers {cov} at the centre — a solid core");
    }

    /// The flow phase is pure in the clock and wraps — a glow that MOVES without a
    /// hidden `Instant::now()`.
    #[test]
    fn the_flow_phase_is_pure_and_wraps() {
        assert!((glow_flow_phase(0.0, 2.0) - 0.0).abs() < 1e-6);
        assert!((glow_flow_phase(1.0, 2.0) - 0.5).abs() < 1e-6);
        assert!((glow_flow_phase(2.0, 2.0) - 0.0).abs() < 1e-6, "one period wraps to 0");
        assert!(
            (glow_flow_phase(3.7, 2.0) - glow_flow_phase(5.7, 2.0)).abs() < 1e-5,
            "pure and periodic",
        );
        // A zero period cannot panic or divide by zero.
        assert!(glow_flow_phase(1.0, 0.0).is_finite());
    }
}

#[cfg(test)]
mod glow_cross_section_tests {
    use super::*;

    /// **RED-WHEN-BROKEN: the cross-section is a PEAK that fades to nothing, and it is
    /// the same ladder the stroke stack reads** (owner, 2026-09-03).
    ///
    /// Three properties, and each one is a thing the stroke stack got wrong:
    ///
    /// 1. **The edge is transparent.** A stack ends on an antialiased boundary; a glow
    ///    ends on nothing. `alpha == 0` at the widest offset.
    /// 2. **Alpha rises monotonically toward the centreline.** No plateau, anywhere —
    ///    the plateau IS the flat band.
    /// 3. **It is the SAME ladder.** The ring alphas are `GLOW_LADDER`'s, in order, so
    ///    this cannot drift into a second opinion about what a glow looks like (LAW 5).
    #[test]
    fn the_cross_section_peaks_at_the_centre_and_fades_to_nothing() {
        for ground in [GlowGround::Dark, GlowGround::Light] {
            let xs = glow_cross_section(1.6, [0.2, 0.8, 1.0], ground);
            assert!(xs.len() >= 3, "a profile needs an edge, some rings and a centre");

            let (edge_off, edge_c) = xs[0];
            assert_eq!(edge_c[3], 0.0, "{ground:?}: the ribbon fades OUT, it does not end on an edge");
            assert!(edge_off > 0.0, "{ground:?}: the edge is off the centreline");

            let (centre_off, centre_c) = *xs.last().expect("a centreline");
            assert_eq!(centre_off, 0.0, "{ground:?}: the profile ends ON the centreline");

            // Offsets march inward; alpha never falls on the way in.
            let mut prev_off = f32::INFINITY;
            let mut prev_a = -1.0f32;
            for (off, c) in &xs {
                assert!(*off <= prev_off, "{ground:?}: offsets go outer → inner, got {off} after {prev_off}");
                assert!(
                    c[3] >= prev_a - 1e-6,
                    "{ground:?}: alpha DIPS on the way in ({} after {prev_a}) — a dip is a ring, \
                     and rings are what made it read as a band",
                    c[3],
                );
                prev_off = *off;
                prev_a = c[3];
            }
            assert!(
                centre_c[3] > edge_c[3],
                "{ground:?}: the centreline must be brighter than the edge",
            );

            // NON-VACUITY: a profile of one flat colour would satisfy "never falls".
            let alphas: Vec<f32> = xs.iter().map(|(_, c)| c[3]).collect();
            let distinct = {
                let mut v = alphas.clone();
                v.sort_by(f32::total_cmp);
                v.dedup_by(|a, b| (*a - *b).abs() < 1e-6);
                v.len()
            };
            assert!(distinct >= 4, "{ground:?}: a real falloff has steps, got {alphas:?}");
        }
    }

    /// **RED-WHEN-BROKEN: it is a PROJECTION of the stroke ladder, not a second one.**
    ///
    /// The graph tracers read `glow_stroke_passes_on` and the map trail reads this. If
    /// the two ever disagreed about the ladder, one surface would drift from the other
    /// and nobody would notice until a screenshot.
    ///
    /// The colours are NOT the passes' own any more, and that is the point: five
    /// stacked translucent strokes composite, so a single ribbon has to carry the
    /// accumulation or it comes out far fainter than the stack it replaces (measured —
    /// core departure 56 against the stack's 204, which is a trail you cannot see).
    /// The accumulation is recomputed HERE, independently, so a cross-section that
    /// invented its own ladder would still be caught.
    #[test]
    fn the_cross_section_carries_the_stroke_ladders_own_rings() {
        let ink = [0.2, 0.8, 1.0];
        let passes = glow_stroke_passes_on(1.6, ink, GlowGround::Dark);
        let xs = glow_cross_section(1.6, ink, GlowGround::Dark);

        let mut want: [f32; 4] = [0.0, 0.0, 0.0, 0.0];
        for (i, (w, c)) in passes.iter().enumerate() {
            // The independent over-composite, written out rather than called, so this
            // test does not simply re-run the code it is checking.
            let (sa, da) = (c[3], want[3]);
            let oa = sa + da * (1.0 - sa);
            want = [
                (c[0] * sa + want[0] * da * (1.0 - sa)) / oa,
                (c[1] * sa + want[1] * da * (1.0 - sa)) / oa,
                (c[2] * sa + want[2] * da * (1.0 - sa)) / oa,
                oa,
            ];

            let (off, xc) = xs[i + 1];
            assert!(
                (off - w * 0.5).abs() < 1e-6,
                "ring {i}: the offset is the PASS's half-width — the widths come from \
                 the ladder even though the colours accumulate",
            );
            for k in 0..4 {
                assert!(
                    (xc[k] - want[k]).abs() < 1e-5,
                    "ring {i} channel {k}: {} vs the composite {}",
                    xc[k],
                    want[k],
                );
            }
            assert!(
                xc[3] >= c[3] - 1e-6,
                "ring {i}: accumulating can only make the ribbon MORE opaque, not less",
            );
        }

        // And the centreline is the whole ladder — the same number `glow_core_coverage`
        // publishes, which is what makes that function and this one one statement.
        let core = xs.last().expect("a centreline");
        assert!((core.0 - 0.0).abs() < 1e-6, "the centreline sits at offset 0");
        assert!(
            (core.1[3] - glow_core_coverage()).abs() < 1e-5,
            "the centre's alpha is the ladder's own coverage: {} vs {}",
            core.1[3],
            glow_core_coverage(),
        );
    }
}