Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GroundZero — site skeleton

A static page generated from a single register. Every record in that register is currently null: nothing has been supplied, and nothing is guessed.

npm run check   # build, then run every gate
npm run serve   # serve public/ on http://localhost:4173

The register

src/config/facts.js holds every external fact as a record:

{
  id: 'contract',
  label: 'Token contract address',
  group: 'contract',
  value: null,          // the fact itself
  source: SOURCE.NONE,  // who vouched for it
  absent: '…',          // the sentence shown while value is null
  present: (v) => v,    // the sentence shown once a value exists
}

A record reads as stated only when it carries both a value and a source. Carrying exactly one of the two is a half-stated fact, and both build.js and scripts/verify.js refuse it.

To publish a fact, set value and source together. That is the only edit required: the panel, the chip, the count, the page description and any control all derive from the record, so a sentence written today cannot survive as a falsehood once the value arrives.

value: null is the honest unknown. It is never a placeholder, an empty string, a zero, or an example.

Render order

The contract record is first in the register and first in the document. It is measured above the fold at every tested viewport.

The copy control

While the contract value is null there is no copy control and no client script on the page. When a value is supplied, the control and its script are emitted together, and the control reads the same element the page displays, so the string a reader sees and the string placed on the clipboard are one expression.

What a stated value has to be

Register integrity asks whether both halves of a fact are present. It does not ask whether what they contain is worth printing, and that gap shipped once: a dry run left 0x000…dead in the contract record with a source beside it, and every gate passed while the page rendered a burn address as a stated fact with a working copy control.

A record may now declare kind: KIND.ADDRESS, and a stated address is rejected by both build.js and scripts/verify.js when it is a burn or vanity address (contains dead or beef), the all-zero address, built from fewer than four distinct hex digits, or contains a paste-in sentinel (example, placeholder, changeme, tbd, todo). It must also be a 0x-prefixed 40 digit hex string.

The limit, stated plainly. This catches values that say nothing. It does not catch values that are wrong. A real, well-formed, deployed contract address that belongs to the wrong contract, the wrong chain, or to somebody else passes every check and always will. Nothing here contacts a network or confirms that code exists at the address. A green build is not confirmation that the address is correct; that stays a human step. The same limit is written beside the rule in src/config/facts.js.

The gate also runs its own matcher against a fixed set of samples on every build, so a regression that quietly stopped rejecting things would be caught while the register is still empty.

Channel slots

The X and repository slots sit in the masthead in both states, so wiring a channel moves nothing on the page.

A channel record carries kind: KIND.URL, and its value is both the text the register prints and the destination the slot navigates to. There is no second table of hrefs to fall out of step with the register, so wiring a channel is a single field edit:

value: 'https://…', source: SOURCE.CLIENT,

One function renders both states. While the record is null the slot is a <span> with role="link", aria-disabled="true" and tabindex="0" — no href, keyboard reachable, inert. Once the record is stated the same call site emits an <a>. A disabled slot and a live link cannot drift, because the gate fails on either mismatch.

The visible reason on hover and focus is the record's own absent sentence, not new wording. The same sentence is always present in the slot's visually hidden label and again in the register row below, so the explanation is never only in a tooltip.

Supplied artwork

public/artwork.jpg is a client file, placed at the client's written instruction. It is re-encoded from pixel data only, so the EXIF and XMP the supplied JPEG carried do not ship.

It sits after the register under its own heading, as a single framed figure. It is deliberately not a row, not a strip, and not next to anything that could read as a list of relationships: it is artwork, not a statement. No record was added for it, nothing in the register refers to it, and no sentence on this page is true or false because of it.

It is never the page's identity. The favicon and the og image are both built from the mark, and a gate fails the build if either points at the artwork, so it cannot become the preview that represents the site.

Its alt is empty and the caption carries the context. Describing the picture would mean writing out what it depicts, and this page does not put that into words.

Palette

src/styles/tokens.css is the only file that names a colour. Every value in it was sampled from a client file and carries its provenance in a comment beside it.

Method: k-means (Lloyd, k-means++ seeding, fixed seed) over the opaque pixels of the RGBA logo for the mark, and over the background region of the flattened logo for the ground. The per-cluster median is taken as the representative value rather than the centroid, so every token is a colour that actually occurs in the file.

Only two hue families appear on this page, because only two appear in the artwork: lime H 62–69 from the mark, blue H 207–217 from the ground. Where a sampled value missed its contrast target, lightness alone was moved and hue and saturation were held; both values are recorded in the comment.

The banner in reference/ was sampled and deliberately not used. Its non-sky clusters are third-party mark colours.

Assets

public/mark.png and public/og.png are generated from the RGBA logo only. The transparent pixels in that file are pure black, so both are produced with a premultiplied resize — premultiply, resample, unpremultiply — otherwise black is dragged into every antialiased edge and the mark gains a dark halo.

Glyph grid

Glyphs are authored in a 48 unit user space and rendered at 48 CSS px. The first child of each is a transparent rect spanning the whole user space, so the hit area is geometry rather than padding. scripts/verify.js re-derives the hit area in CSS pixels from the emitted viewBox and width attributes, so changing the grid changes the measurement rather than silently invalidating it.

The supplied artwork is a mark, not an icon set, so the glyphs remain neutral geometric forms. No third-party mark is drawn.

Gates

scripts/verify.js runs eleven gates and exits non-zero on any failure:

gate fails when
register integrity a value has no source, a source has no value, or a stated channel's value is not an absolute https url
stated values say something a stated address is a burn or vanity address, all-zero, built from too few distinct nibbles, or a pasted sentinel
channel slots a slot links while its record is null, renders disabled while its record is stated, is not keyboard reachable, or its href differs from the value it displays
supplied artwork the artwork is missing, is used as the favicon or og image, or sits inside the register
reference terms a term from the studied reference appears in a shipped file
authorship attribution assistant authorship is credited anywhere, dotfiles included
emitted html comments the shipped document contains any comment
image metadata a shipped image carries a text or EXIF segment
tap targets a glyph's hit area is under 44 CSS px once viewBox scaling is applied
token contrast any token misses its target on either painted ground
orphan copy control a copy control or a script appears while the address is null

Deny lists are stored as SHA-256 digests of the normalised term, never as text. Matching runs the other way round: text under test is normalised, cut into n-grams, hashed, and looked up. A published gate file therefore cannot be read back into the words it rejects.

Each gate has been broken deliberately and observed to fail before being accepted as passing.

Layout measurement

Measured in a real engine against the effective viewport, with browser chrome subtracted from the nominal device size. With the page served, run:

(() => {
  const H = innerHeight, W = innerWidth;
  const q = (s) => document.querySelector(s)?.getBoundingClientRect();
  return {
    viewport: W + 'x' + H,
    contractBottom: q('#contract')?.bottom,
    aboveFold: q('#contract')?.bottom <= H,
    horizontalScroll: document.documentElement.scrollWidth > W,
  };
})()

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages