Living Document Notice
Published 2026-09-12. The evolving architecture, revisions, and connected notes for this dispatch live in the Stax Digital Garden.

P7 Phosphor Decay and Calm Background Observatories

P7 Phosphor Decay and Calm Background Observatories: Nocturnal deep violet and spectral green dual-trace CRT macro showing PPI polar radar sweep with natural phosphor decay trail

Summary

Modern monitoring dashboards demand attention through high-contrast alerts, pulsing red badges, and abrupt CSS micro-interactions. When deployed as ambient displays on peripheral monitors, these design conventions produce sensory fatigue and visual distraction. Historical radar scopes avoided this problem entirely through physical materials: cathode ray tubes coated with dual-layer P7 cascade phosphor produced an instantaneous excitation flash followed by an elegant, protracted afterglow.

Hushwire translates the physics of P7 phosphor into an efficient HTML5 Canvas accumulation pipeline. By combining exponential luminance decay curves with low-saturation amber and green palettes, the radar interface renders multi-minute flight paths directly on the glass. Motion over time becomes legible at a glance without requiring active user focus, animation loops, or intrusive UI notifications. This dispatch covers the decay mathematics, canvas buffer implementation, and ergonomics of calm visual instruments.

The Material Physics of P7 Phosphor

During the mid-twentieth century, air traffic and naval radar systems faced a fundamental challenge: mechanical antennas rotated at slow speeds (typically 6 to 12 revolutions per minute), meaning each contact was refreshed only once every 5 to 10 seconds. Standard short-persistence phosphors faded within milliseconds, leaving operators staring at a dark screen between sweeps.

Engineers resolved this by formulating P7 phosphor, a cascade compound consisting of two distinct crystalline layers:

  1. Excitation Layer (Zinc Sulfide: Silver): Activated directly by the electron beam, producing a sharp, blue-white primary flash lasting approximately 0.1 milliseconds.
  2. Storage and Emission Layer (Zinc Cadmium Sulfide: Copper): Absorbed the blue-white photons from the initial layer and re-emitted them as a warm yellow-green luminance (555 nm) that decayed gradually over several seconds to minutes.
Electron Beam
    │
    ▼
┌─────────────────────────────────┐
│ Layer 1: ZnS:Ag (Blue Flash)    │  τ < 0.1 ms
└───────────────┬─────────────────┘
                │ Photon Transfer (440 nm)
                ▼
┌─────────────────────────────────┐
│ Layer 2: (Zn,Cd)S:Cu (Afterglow)│  τ ≈ 3 to 15 s
└─────────────────────────────────┘
                │
                ▼ Human Eye (555 nm Peak Sensitivity)

This delayed luminescence provided two essential information properties: it naturally visualized direction and speed (the brightest point represented current position, while the fading tail revealed previous trajectory), and it eliminated the need for human operators to consciously track coordinate deltas across sweeps.

Mathematical Modeling of the Decay Tail

While simple linear fades produce an artificial, stepped appearance, true phosphor phosphorescence adheres to a bimolecular recombination decay model, closely approximated by a modified power-law or dual-exponential curve:

Where:

  • is the elapsed time in seconds since the radar sweep line intersected the target.
  • represents the rapid primary decay constant (0.05 s).
  • represents the protracted lattice emission constant (3.5 s).
  • is the empirical decay exponent, typically between 0.9 and 1.2 for P7 compounds.

For real-time canvas rendering at 60 Hz, computing full power-law decay per particle across hundreds of historical coordinates wastes CPU cycles. Instead, Hushwire models decay as an iterative frame attenuation operation on an offscreen accumulation buffer.

Accumulation Buffer Architecture

Rather than redrawing the full historical track of every aircraft on every tick, Hushwire maintains two separate canvas contexts:

  1. Accumulation Canvas (ctxAccum): Stores decaying trail history. On each render cycle, it is slightly attenuated using a translucent clear rect and receives newly drawn contact blips.
  2. Foreground Scope Canvas (ctxMain): Composites the accumulated trails, paints the rotating sweep line, and draws current crisp vector text labels.
Telemetry Ingestion ──► Draw Current Blip ──► [ Accumulation Canvas ]
                                                       │
                                            Frame-to-Frame Decay Pass
                                            (globalCompositeOperation)
                                                       │
                                                       ▼
[ Foreground Canvas ] ◄── Merge Trails Layer ──────────┘
        │
        ├── Draw Bearing Rings & Grids
        ├── Draw Vector Callouts & Data Tags
        └── Present to Screen

Canvas Decay Implementation

class PhosphorScope {
  constructor(canvas, width, height) {
    this.canvas = canvas;
    this.ctx = canvas.getContext("2d");
    this.width = width;
    this.height = height;
 
    // Offscreen accumulation buffer
    this.trailCanvas = document.createElement("canvas");
    this.trailCanvas.width = width;
    this.trailCanvas.height = height;
    this.trailCtx = this.trailCanvas.getContext("2d");
 
    // Clear background to deep cathode black
    this.trailCtx.fillStyle = "#070b0a";
    this.trailCtx.fillRect(0, 0, width, height);
 
    // Attenuation rate: higher alpha = faster fade
    // 0.025 at 60 FPS creates a ~4.5 second visible retention tail
    this.decayAlpha = 0.025;
  }
 
  // Invoked on each animation frame
  public stepDecay() {
    this.trailCtx.save();
    // Fade existing contents toward background
    this.trailCtx.globalCompositeOperation = "source-over";
    this.trailCtx.fillStyle = `rgba(7, 11, 10, ${this.decayAlpha})`;
    this.trailCtx.fillRect(0, 0, this.width, this.height);
    this.trailCtx.restore();
  }
 
  // Paint an active contact blip to the accumulation layer
  public recordContact(x, y, isPrimaryHit) {
    this.trailCtx.save();
    if (isPrimaryHit) {
      // P7 Primary Excitation Flash (Blue-white center)
      this.trailCtx.fillStyle = "#e0fbfc";
      this.trailCtx.shadowColor = "#98c1d9";
      this.trailCtx.shadowBlur = 8;
      this.trailCtx.beginPath();
      this.trailCtx.arc(x, y, 2.5, 0, Math.PI * 2);
      this.trailCtx.fill();
    }
 
    // Secondary Luminescent Ring (Amber or Phosphor Green)
    this.trailCtx.fillStyle = "#2a9d8f";
    this.trailCtx.shadowColor = "#2a9d8f";
    this.trailCtx.shadowBlur = 12;
    this.trailCtx.beginPath();
    this.trailCtx.arc(x, y, 4.0, 0, Math.PI * 2);
    this.trailCtx.fill();
    this.trailCtx.restore();
  }
 
  // Composite the final scene to the visible canvas
  public render(activeContacts, sweepAngle) {
    this.stepDecay();
 
    // 1. Clear foreground
    this.ctx.fillStyle = "#070b0a";
    this.ctx.fillRect(0, 0, this.width, this.height);
 
    // 2. Render accumulated trails
    this.ctx.drawImage(this.trailCanvas, 0, 0);
 
    // 3. Draw Range Rings and Azimuth Grid
    this.drawRangeRings();
 
    // 4. Draw Radar Sweep Line
    this.drawSweepLine(sweepAngle);
 
    // 5. Draw Active Metadata Overlay
    for (const ac of activeContacts) {
      this.drawAircraftTag(ac);
    }
  }
 
  private drawRangeRings() {
    this.ctx.strokeStyle = "rgba(42, 157, 143, 0.12)";
    this.ctx.lineWidth = 1;
    const cx = this.width / 2;
    const cy = this.height / 2;
    [50, 100, 150, 200, 250].forEach(r => {
      this.ctx.beginPath();
      this.ctx.arc(cx, cy, r, 0, Math.PI * 2);
      this.ctx.stroke();
    });
  }
 
  private drawSweepLine(angleRad) {
    const cx = this.width / 2;
    const cy = this.height / 2;
    const maxR = Math.hypot(cx, cy);
 
    this.ctx.save();
    this.ctx.strokeStyle = "rgba(152, 193, 217, 0.45)";
    this.ctx.lineWidth = 1.5;
    this.ctx.beginPath();
    this.ctx.moveTo(cx, cy);
    this.ctx.lineTo(cx + maxR * Math.cos(angleRad), cy + maxR * Math.sin(angleRad));
    this.ctx.stroke();
    this.ctx.restore();
  }
 
  private drawAircraftTag(ac) {
    // Sharp, high-legibility callouts above the decay layer
    this.ctx.fillStyle = "#e0fbfc";
    this.ctx.font = "10px monospace";
    this.ctx.fillText(`${ac.callsign} ${ac.alt}ft`, ac.x + 8, ac.y - 4);
  }
}

Ergonomics of the Calm Secondary Display

Designing an instrument for ambient observation requires strict visual restraint:

Visual DimensionAggressive Web DashboardHushwire Calm Scope
Peak Screen Luminance85% to 100% white backgrounds18% maximum phosphor luminance ceiling
Animation TriggersPulsing CSS badges, sliding notificationsConstant-velocity radial sweep; continuous decay
State NotificationsToast popups, browser bell chimesSilent state transitions within existing glyphs
Cognitive IngressForces immediate foreground attentionPeripheral legibility; readable only when looked at

By anchoring the visual architecture to physical phosphor decay, Hushwire provides situational awareness of local skies without competing for cognitive bandwidth. The operator glances over, reads flight tracks formed by organic light trails, and returns to their primary task without friction.


  • Directus Target: hushwire
  • Garden Source Reference: Phosphor Decay Algorithms, Calm Computing, UI Instruments, MOC - Fleet Operations, MOC - Bosun PKM Tools