1. readsGitHub's live status feed
  2. becomesincident involvement → mass; severity → heat
  3. writes--w--cat
  4. you seetroubled services swell and warm; quiet ones recede to gray

No canvas is drawn here — the field is invisible; these variables are its only output. Without it you would build: a status table with severity badges.

field-ui · invisible fields · fleet

Incidents accrete.

A status page is a fleet pretending to be a checklist: every service gets the same green dot, and yesterday's outage evaporates at midnight. This is GitHub's real status page run as a field: each service carries the weight of its incident history — the more of the window's 29 incidents name it, the heavier it reads — and each incident is a sink that accreted updates, one report at a time, until resolution released it.

Impact is the heat: a dim gray blip barely registers, a critical burns red — and that color anchors the whole row. Hover an incident and the services it hit light up in the grid; hover a service and its incidents light in the timeline. Click an incident to open the updates it accreted. Toggle the field off and the page collapses back to the checklist.

Field
Weight services by

size = involvement — how many of the 29 incidents named each service · color = impact — the incident's declared severity, dim none → red critical

The fleet 11 services snapshot · 2026-06-10

  • Actions operational 6 incidents in this window
  • Git Operations operational 3 incidents in this window
  • Pull Requests operational 3 incidents in this window
  • Webhooks operational 2 incidents in this window
  • Issues operational 2 incidents in this window
  • Pages operational 2 incidents in this window
  • Copilot operational 2 incidents in this window
  • API Requests operational 1 incident in this window
  • Packages operational 1 incident in this window
  • Codespaces operational 0 incidents in this window
  • Copilot AI Model Providers operational 0 incidents in this window

The timeline 29 incidents, newest first

How it's built

Both zones are ordinary semantic HTML — a <ul> of services, an <ol> of incidents — carrying the status API's numbers as data attributes. field-ui runs an invisible field over the page and the type carries the measurement: involvement as weight, impact as heat, accretion as a fill bar. Two live channels ride on top: the page's hidden engine writes --d (local particle density) to every data-hot card each frame, and the scoped recipe's attention lane writes an eased --field-attention — CSS turns both into a felt glow and lift. The load bars also sweep in only at reading pace, gated by the engine's live --field-scroll-v. And the grid is live: the runtime re-polls the components feed every minute and diffs each card's status pill in place — a changed card pulses once and holds data-active for ~3 seconds, which the attention metric reads as engagement. The field literally notices the change.

1 — services and incidents are bodies

HTML
<!-- a service: involvement is mass -->
<li id="comp-actions"
  data-body="attract"
  data-strength="1.99"
  data-feedback data-hot
  data-inv="6" data-last="1780..."
  style="--w: 1.0; --cat: #2dd4bf;">

<!-- an incident: impact is the heat -->
<li id="inc-h2vk60..."
  data-body="attract"
  data-feedback data-hot
  data-comps="issues pull-requests actions"
  style="--w: 0.74; --cat: #f87171;">
  ...
  <!-- the load bar declares itself a
       measurement of its incident -->
  <span class="fl-load"
        data-field-visual-for="#inc-h2vk60..."
        data-field-visual-role="measurement">
    <i style="--fill: 62%"></i>
  </span>
</li>
  • data-inv / data-last — the signals the lens re-weights
  • data-comps — the cross-highlight edges, by service name
  • --cat — the impact heat the CSS mixes into the anchor
  • data-hot — opts into the live density gather: hover and --d climbs toward 1
  • data-field-visual-for — names the load bar a measurement of its incident

2 — accretion is the updates an incident held

CSS
/* the fill bar: this incident's update
   count over the window's max (10) —
   static math over the snapshot. */
.fl-load i { width: var(--fill, 100%); }

/* entry sweep: 0 → recorded fill, but only
   once the bar is on screen AND the engine's
   --field-scroll-v reads under 2 px/frame
   (reading pace). Skipped entirely under
   prefers-reduced-motion. */
@media (prefers-reduced-motion: no-preference) {
  [data-fl-sweep] .fl-inc:not([data-swept])
    .fl-load i { width: 0; }
  .fl-load i { transition: width 0.7s; }
}

/* the live channels: --d (local density,
   gathers on data-hot hover) glows the card;
   the impact chip runs hotter with it. */
.fl-comp {
  --live: var(--d, 0);
  box-shadow: 0 0 calc(var(--live) * 16px) -6px
    color-mix(in srgb, var(--cat)
      calc(var(--live) * 55%), transparent);
}

Kept honest: the fill width is arithmetic over the snapshot's updates[] — the sink/accretion concept rendered from recorded history. The live writes are separate and named: --field-scroll-v paces the entry sweep, --d and --field-attention drive the glow.

3 — cross-lighting, and the live poll

// hover an incident → light the
// services it names
for (const s of inc.dataset.comps.split(" "))
  grid.querySelector("#comp-" + s)
    ?.classList.add("cited");

// hover a service → light its incidents
incidents.filter((i) =>
  i.dataset.comps.split(" ").includes(name)
).forEach((i) => i.classList.add("cited"));

// class highlights only — no SVG here.
// the glow channel rides along for free:
// hovering is what makes --d gather.

The service lens re-weights the grid (involvement or most-recently-hit) and FLIP re-sorts it in two dimensions — grid moves are x and y. The poll loop never throws: three consecutive failures and the chip falls back to the snapshot date and the interval retires itself.