OVERSCANUI KIT
no button at all a worn bezel with weight channels do not converge zero depth instrumented, full of smoke a field of real characters a camera looking out additive, so no shadow hairlines, no new shader no raster, so no scanlines

Ten shaders, and which KIND a shader is decides where it is allowed to sit. The kit's constraint has always been that a GLSL pass cannot sample the DOM. That is true, and the rule first drawn from it was one step too strong: it says nothing about drawing over the DOM. The real test is whether an effect needs the image beneath it. Scanlines, vignette, bloom and chroma all MULTIPLY with what is under them, so they stay CSS forever. A field, an instrument interior, an ornament and a screen fault do not — a dead pixel is black over a chart and black over an empty panel — which is exactly why a fault may be drawn on top and a CRT finish may not.

🔴 One WebGL context for all of it. A browser will not give a page a context per element: Chrome's cap is about 16, and past it getContext does not return null, it EVICTS the oldest and that canvas goes blank with no error at all. Measured at 17 by glcheck. So every element here shares one context and blits its result out, which is why the number of shaders on a page is bounded by time rather than by the browser.

every shader, in the theme that uses it

Each sample runs in its own theme, because a shader shown in someone else's palette is being shown in the wrong register.

field.glsl field

One parameterised texture: wash, scanline, grain, vignette, haze, chroma, glitch. The registers differ in how much of each term they use rather than in mechanism, so a shader per theme would be variation encoding nothing.

sits behind everything, as the surface the UI sits on

used by terminal, industrial, cyber, esper, aegis

rain.glsl field

The field is made of CHARACTERS. Half-width katakana rasterised into a texture and sampled per cell, mirrored the way the film mirrors them, columns falling at their own speeds behind a bright leading glyph.

sits behind everything, as the surface the UI sits on

used by neo

vision.glsl field

The only field here that is a CAMERA looking out rather than a screen being looked at: interlace, fixed pattern noise that does not move between frames, a readout sweep, dropout bands.

sits behind everything, as the surface the UI sits on

used by machina

holo.glsl field

Projected rather than printed, so it is purely ADDITIVE: light cannot be darker than the room. The banding drifts instead of sitting still, and the colour channels do not converge.

sits behind everything, as the surface the UI sits on

used by holo

beam.glsl field

The only field here that is not SIMULTANEOUS. A raster has one age; an X-Y display has a display list, so the brightness gradient across the picture is DRAW ORDER. Dwell burns the corners, the beam overshoots them, and imperfect blanking leaves the retrace visible between figures.

sits behind everything, as the surface the UI sits on

used by vector

filmloop.glsl instrument interior

Not a field: an INSTRUMENT. A film loop held to about 2Hz by u_hold, because a 2001 readout is a loop nobody operates. antiseptic has no field at all, which is its register rather than an omission.

sits inside its own box, drawing real data

used by antiseptic

scope.glsl instrument interior

Beam intensity is DWELL TIME: a real beam deposits light per unit time, not per unit length, so it burns on flat tops and vanishes on the edges. The one thing a stroked polyline cannot express.

sits inside its own box, drawing real data

used by any

waterfall.glsl instrument interior

Time, frequency and intensity at once. Every colour map is monotonic in lightness, because a rainbow invents structure: its perceptual edges read as boundaries in the data when they are boundaries in the palette.

sits inside its own box, drawing real data

used by any

ornament.glsl ornament

Decoration that encodes NOTHING and says so: aria-hidden, and forbidden the geometry of an instrument. Four modes, chosen per THEME, because "which ornament is this" is not a question an ornament should answer.

sits in flow, or behind a panel, encoding nothing

used by all nine

fault.glsl fault
vend 4system nominal
core temp318.4 K
flux0.912

Damage to the GLASS rather than to the image: burn-in from a retired layout, a dead column, stuck subpixels. Declared, never detected. The one shader allowed to sit OVER the interface.

sits OVER the interface, because it never reads what is under it

used by any

where a field may be scoped

A field is usually the whole surface, but an <ov-field> inside a panel is scoped to that panel, because the panel is the nearest positioned ancestor and the panel's own child rule excludes ov-field by name. antiseptic has to name the shader in the attribute: its theme sets none, and that is its register rather than an oversight.

panel, no field
VENT A
FLUX 0.912
the default: the panel's own background, with the page field behind the whole surface
panel, own field
VENT B
FLUX 0.912
an <ov-field> INSIDE the panel, scoped to it
panel, ornament behind
VENT C
FLUX 0.912
decoration as a backdrop rather than a field. it reports nothing and is aria-hidden

the four ornament modes

The mode is a theme decision, not a per-element one, so every ornament on a surface moves the same way. All four are shown together only so they can be compared. An ornament may never be given the geometry of a readout — no bars of varying height, no needle, no trace against an axis — because in a kit whose thesis is that a readout refuses to invent, an ornament shaped like a readout is the worst thing on the page.

sweep · terminal, antiseptic, aegis
strata · industrial, machina
strands · cyber, neo
smoke · esper, holo
demo/shader.html, from this page
import 'overscan'
import 'overscan/overscan.css'

<ov-field shader="field"></ov-field>
variation: shader="rain"
import 'overscan'
import 'overscan/overscan.css'

<ov-field shader="rain"></ov-field>
variation: shader="vision"
import 'overscan'
import 'overscan/overscan.css'

<ov-field shader="vision"></ov-field>
variation: shader="holo"
import 'overscan'
import 'overscan/overscan.css'

<ov-field shader="holo"></ov-field>